@ydbjs/topic
Version:
YDB Topics client for publish-subscribe messaging. Provides at-least-once delivery, exactly-once publishing, FIFO guarantees, and scalable message processing for unstructured data.
101 lines • 2.9 kB
JavaScript
export class AsyncPriorityQueue {
paused = false;
closed = false;
heap = [];
pendingShift;
pendingResume;
get size() {
return this.heap.length;
}
push(value, priority = 0) {
if (this.closed) {
throw new Error('Queue closed');
}
let left = 0;
let right = this.heap.length;
while (left < right) {
let mid = (left + right) >> 1;
if (this.heap[mid].priority < priority) {
right = mid;
}
else {
left = mid + 1;
}
}
this.heap.splice(left, 0, { value, priority });
if (this.pendingShift && this.heap.length > 0) {
const next = this.heap.shift();
const resolve = this.pendingShift;
delete this.pendingShift;
resolve({ value: next.value, done: false });
}
}
async next() {
if (this.paused) {
await new Promise((resolve) => {
this.pendingResume = resolve;
});
}
// Return done if closed and no items to process
if (this.closed && this.heap.length === 0) {
return { value: undefined, done: true };
}
if (this.heap.length > 0) {
let next = this.heap.shift();
return { value: next.value, done: false };
}
// If we reach here: not closed and no items in heap
// Create pending operation to wait for new items
return new Promise((resolve) => {
this.pendingShift = resolve;
});
}
pause() {
this.paused = true;
}
resume() {
if (!this.paused) {
return;
}
this.paused = false;
if (this.pendingResume) {
const resolve = this.pendingResume;
delete this.pendingResume;
resolve();
}
}
close() {
this.closed = true;
// Resolve any pending operations with done: true
if (this.pendingShift) {
let resolve = this.pendingShift;
delete this.pendingShift;
resolve({ value: undefined, done: true });
}
if (this.pendingResume) {
let resolve = this.pendingResume;
delete this.pendingResume;
resolve();
}
}
dispose() {
// Clear the heap to prevent memory leaks
this.heap.length = 0;
// Close and resolve pending operations
this.close();
}
async *[Symbol.asyncIterator]() {
while (true) {
// eslint-disable-next-line no-await-in-loop
let { value, done } = await this.next();
if (done) {
break;
}
yield value;
}
}
[Symbol.dispose]() {
this.dispose();
}
}
//# sourceMappingURL=queue.js.map