UNPKG

yqueue

Version:

Yet another concurrent task queue

58 lines 2.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.YQueue = exports.DEFAULT_QUEUE_CONCURRENCY = void 0; const binary_heap_1 = require("./binary-heap"); const y_semaphore_1 = require("./y-semaphore"); exports.DEFAULT_QUEUE_CONCURRENCY = 10; class YQueue { constructor(options) { var _a; this.options = options; this.onIdleWaits = []; let concurrency = (_a = options === null || options === void 0 ? void 0 : options.concurrency) !== null && _a !== void 0 ? _a : exports.DEFAULT_QUEUE_CONCURRENCY; if (!(concurrency >= 1)) concurrency = exports.DEFAULT_QUEUE_CONCURRENCY; this.concurrency = concurrency; this.semaphore = new y_semaphore_1.YSemaphore(concurrency); this.onQueueLessThanWaits = new binary_heap_1.BinaryHeap((a, b) => a.threshold - b.threshold); } async run(fn, options) { const acquired = await this.semaphore.acquire(options === null || options === void 0 ? void 0 : options.priority); try { return await fn(); } finally { this.semaphore.release(acquired); if (this.semaphore.getAvailablePermits() === this.semaphore.permits) { this.onIdleWaits.forEach(f => f()); this.onIdleWaits = []; } const queueLength = this.semaphore.getQueueLength(); for (;;) { const next = this.onQueueLessThanWaits.peek(); if (next === null || queueLength >= next.threshold) break; next.ack(); this.onQueueLessThanWaits.removeMax(); } } } add(fn, options) { this.run(fn, options); } onIdle() { if (this.semaphore.getAvailablePermits() === this.semaphore.permits) { return Promise.resolve(); } return new Promise(f => this.onIdleWaits.push(f)); } onQueueSizeLessThan(size) { if (this.semaphore.getQueueLength() < (size > 0 ? size : 1)) { return Promise.resolve(); } return new Promise(f => this.onQueueLessThanWaits.add({ ack: f, threshold: size })); } } exports.YQueue = YQueue; exports.default = YQueue; //# sourceMappingURL=y-queue.js.map