Comparing version 7.4.1 to 8.0.0
import { EventEmitter } from 'eventemitter3'; | ||
import { Queue, RunFunction } from './queue.js'; | ||
import { type Queue, type RunFunction } from './queue.js'; | ||
import PriorityQueue from './priority-queue.js'; | ||
import { QueueAddOptions, Options, TaskOptions } from './options.js'; | ||
import { type QueueAddOptions, type Options, type TaskOptions } from './options.js'; | ||
type Task<TaskResultType> = ((options: TaskOptions) => PromiseLike<TaskResultType>) | ((options: TaskOptions) => TaskResultType); | ||
/** | ||
The error thrown by `queue.add()` when a job is aborted before it is run. See `signal`. | ||
*/ | ||
export declare class AbortError extends Error { | ||
} | ||
type EventName = 'active' | 'idle' | 'empty' | 'add' | 'next' | 'completed' | 'error'; | ||
@@ -93,2 +88,3 @@ /** | ||
} | ||
export { Queue, QueueAddOptions, QueueAddOptions as DefaultAddOptions, Options }; | ||
export type { Queue } from './queue.js'; | ||
export { type QueueAddOptions, type Options } from './options.js'; |
@@ -1,13 +0,1 @@ | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _PQueue_instances, _PQueue_carryoverConcurrencyCount, _PQueue_isIntervalIgnored, _PQueue_intervalCount, _PQueue_intervalCap, _PQueue_interval, _PQueue_intervalEnd, _PQueue_intervalId, _PQueue_timeoutId, _PQueue_queue, _PQueue_queueClass, _PQueue_pending, _PQueue_concurrency, _PQueue_isPaused, _PQueue_throwOnTimeout, _PQueue_doesIntervalAllowAnother_get, _PQueue_doesConcurrentAllowAnother_get, _PQueue_next, _PQueue_onResumeInterval, _PQueue_isIntervalPaused_get, _PQueue_tryToStartAnother, _PQueue_initializeIntervalIfNeeded, _PQueue_onInterval, _PQueue_processQueue, _PQueue_throwOnAbort, _PQueue_onEvent; | ||
import { EventEmitter } from 'eventemitter3'; | ||
@@ -17,41 +5,29 @@ import pTimeout, { TimeoutError } from 'p-timeout'; | ||
/** | ||
The error thrown by `queue.add()` when a job is aborted before it is run. See `signal`. | ||
*/ | ||
export class AbortError extends Error { | ||
} | ||
/** | ||
Promise queue with concurrency control. | ||
*/ | ||
class PQueue extends EventEmitter { | ||
export default class PQueue extends EventEmitter { | ||
#carryoverConcurrencyCount; | ||
#isIntervalIgnored; | ||
#intervalCount = 0; | ||
#intervalCap; | ||
#interval; | ||
#intervalEnd = 0; | ||
#intervalId; | ||
#timeoutId; | ||
#queue; | ||
#queueClass; | ||
#pending = 0; | ||
// The `!` is needed because of https://github.com/microsoft/TypeScript/issues/32194 | ||
#concurrency; | ||
#isPaused; | ||
#throwOnTimeout; | ||
/** | ||
Per-operation timeout in milliseconds. Operations fulfill once `timeout` elapses if they haven't already. | ||
Applies to each future operation. | ||
*/ | ||
timeout; | ||
// TODO: The `throwOnTimeout` option should affect the return types of `add()` and `addAll()` | ||
constructor(options) { | ||
var _a, _b, _c, _d; | ||
super(); | ||
_PQueue_instances.add(this); | ||
_PQueue_carryoverConcurrencyCount.set(this, void 0); | ||
_PQueue_isIntervalIgnored.set(this, void 0); | ||
_PQueue_intervalCount.set(this, 0); | ||
_PQueue_intervalCap.set(this, void 0); | ||
_PQueue_interval.set(this, void 0); | ||
_PQueue_intervalEnd.set(this, 0); | ||
_PQueue_intervalId.set(this, void 0); | ||
_PQueue_timeoutId.set(this, void 0); | ||
_PQueue_queue.set(this, void 0); | ||
_PQueue_queueClass.set(this, void 0); | ||
_PQueue_pending.set(this, 0); | ||
// The `!` is needed because of https://github.com/microsoft/TypeScript/issues/32194 | ||
_PQueue_concurrency.set(this, void 0); | ||
_PQueue_isPaused.set(this, void 0); | ||
_PQueue_throwOnTimeout.set(this, void 0); | ||
/** | ||
Per-operation timeout in milliseconds. Operations fulfill once `timeout` elapses if they haven't already. | ||
Applies to each future operation. | ||
*/ | ||
Object.defineProperty(this, "timeout", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
@@ -68,20 +44,112 @@ options = { | ||
if (!(typeof options.intervalCap === 'number' && options.intervalCap >= 1)) { | ||
throw new TypeError(`Expected \`intervalCap\` to be a number from 1 and up, got \`${(_b = (_a = options.intervalCap) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ''}\` (${typeof options.intervalCap})`); | ||
throw new TypeError(`Expected \`intervalCap\` to be a number from 1 and up, got \`${options.intervalCap?.toString() ?? ''}\` (${typeof options.intervalCap})`); | ||
} | ||
if (options.interval === undefined || !(Number.isFinite(options.interval) && options.interval >= 0)) { | ||
throw new TypeError(`Expected \`interval\` to be a finite number >= 0, got \`${(_d = (_c = options.interval) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : ''}\` (${typeof options.interval})`); | ||
throw new TypeError(`Expected \`interval\` to be a finite number >= 0, got \`${options.interval?.toString() ?? ''}\` (${typeof options.interval})`); | ||
} | ||
__classPrivateFieldSet(this, _PQueue_carryoverConcurrencyCount, options.carryoverConcurrencyCount, "f"); | ||
__classPrivateFieldSet(this, _PQueue_isIntervalIgnored, options.intervalCap === Number.POSITIVE_INFINITY || options.interval === 0, "f"); | ||
__classPrivateFieldSet(this, _PQueue_intervalCap, options.intervalCap, "f"); | ||
__classPrivateFieldSet(this, _PQueue_interval, options.interval, "f"); | ||
__classPrivateFieldSet(this, _PQueue_queue, new options.queueClass(), "f"); | ||
__classPrivateFieldSet(this, _PQueue_queueClass, options.queueClass, "f"); | ||
this.#carryoverConcurrencyCount = options.carryoverConcurrencyCount; | ||
this.#isIntervalIgnored = options.intervalCap === Number.POSITIVE_INFINITY || options.interval === 0; | ||
this.#intervalCap = options.intervalCap; | ||
this.#interval = options.interval; | ||
this.#queue = new options.queueClass(); | ||
this.#queueClass = options.queueClass; | ||
this.concurrency = options.concurrency; | ||
this.timeout = options.timeout; | ||
__classPrivateFieldSet(this, _PQueue_throwOnTimeout, options.throwOnTimeout === true, "f"); | ||
__classPrivateFieldSet(this, _PQueue_isPaused, options.autoStart === false, "f"); | ||
this.#throwOnTimeout = options.throwOnTimeout === true; | ||
this.#isPaused = options.autoStart === false; | ||
} | ||
get #doesIntervalAllowAnother() { | ||
return this.#isIntervalIgnored || this.#intervalCount < this.#intervalCap; | ||
} | ||
get #doesConcurrentAllowAnother() { | ||
return this.#pending < this.#concurrency; | ||
} | ||
#next() { | ||
this.#pending--; | ||
this.#tryToStartAnother(); | ||
this.emit('next'); | ||
} | ||
#onResumeInterval() { | ||
this.#onInterval(); | ||
this.#initializeIntervalIfNeeded(); | ||
this.#timeoutId = undefined; | ||
} | ||
get #isIntervalPaused() { | ||
const now = Date.now(); | ||
if (this.#intervalId === undefined) { | ||
const delay = this.#intervalEnd - now; | ||
if (delay < 0) { | ||
// Act as the interval was done | ||
// We don't need to resume it here because it will be resumed on line 160 | ||
this.#intervalCount = (this.#carryoverConcurrencyCount) ? this.#pending : 0; | ||
} | ||
else { | ||
// Act as the interval is pending | ||
if (this.#timeoutId === undefined) { | ||
this.#timeoutId = setTimeout(() => { | ||
this.#onResumeInterval(); | ||
}, delay); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
#tryToStartAnother() { | ||
if (this.#queue.size === 0) { | ||
// We can clear the interval ("pause") | ||
// Because we can redo it later ("resume") | ||
if (this.#intervalId) { | ||
clearInterval(this.#intervalId); | ||
} | ||
this.#intervalId = undefined; | ||
this.emit('empty'); | ||
if (this.#pending === 0) { | ||
this.emit('idle'); | ||
} | ||
return false; | ||
} | ||
if (!this.#isPaused) { | ||
const canInitializeInterval = !this.#isIntervalPaused; | ||
if (this.#doesIntervalAllowAnother && this.#doesConcurrentAllowAnother) { | ||
const job = this.#queue.dequeue(); | ||
if (!job) { | ||
return false; | ||
} | ||
this.emit('active'); | ||
job(); | ||
if (canInitializeInterval) { | ||
this.#initializeIntervalIfNeeded(); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
#initializeIntervalIfNeeded() { | ||
if (this.#isIntervalIgnored || this.#intervalId !== undefined) { | ||
return; | ||
} | ||
this.#intervalId = setInterval(() => { | ||
this.#onInterval(); | ||
}, this.#interval); | ||
this.#intervalEnd = Date.now() + this.#interval; | ||
} | ||
#onInterval() { | ||
if (this.#intervalCount === 0 && this.#pending === 0 && this.#intervalId) { | ||
clearInterval(this.#intervalId); | ||
this.#intervalId = undefined; | ||
} | ||
this.#intervalCount = this.#carryoverConcurrencyCount ? this.#pending : 0; | ||
this.#processQueue(); | ||
} | ||
/** | ||
Executes all queued functions until it reaches the limit. | ||
*/ | ||
#processQueue() { | ||
// eslint-disable-next-line no-empty | ||
while (this.#tryToStartAnother()) { } | ||
} | ||
get concurrency() { | ||
return __classPrivateFieldGet(this, _PQueue_concurrency, "f"); | ||
return this.#concurrency; | ||
} | ||
@@ -92,29 +160,30 @@ set concurrency(newConcurrency) { | ||
} | ||
__classPrivateFieldSet(this, _PQueue_concurrency, newConcurrency, "f"); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_processQueue).call(this); | ||
this.#concurrency = newConcurrency; | ||
this.#processQueue(); | ||
} | ||
async #throwOnAbort(signal) { | ||
return new Promise((_resolve, reject) => { | ||
signal.addEventListener('abort', () => { | ||
reject(signal.reason); | ||
}, { once: true }); | ||
}); | ||
} | ||
async add(function_, options = {}) { | ||
options = { | ||
timeout: this.timeout, | ||
throwOnTimeout: __classPrivateFieldGet(this, _PQueue_throwOnTimeout, "f"), | ||
throwOnTimeout: this.#throwOnTimeout, | ||
...options, | ||
}; | ||
return new Promise((resolve, reject) => { | ||
__classPrivateFieldGet(this, _PQueue_queue, "f").enqueue(async () => { | ||
var _a; | ||
var _b, _c; | ||
__classPrivateFieldSet(this, _PQueue_pending, (_b = __classPrivateFieldGet(this, _PQueue_pending, "f"), _b++, _b), "f"); | ||
__classPrivateFieldSet(this, _PQueue_intervalCount, (_c = __classPrivateFieldGet(this, _PQueue_intervalCount, "f"), _c++, _c), "f"); | ||
this.#queue.enqueue(async () => { | ||
this.#pending++; | ||
this.#intervalCount++; | ||
try { | ||
// TODO: Use options.signal?.throwIfAborted() when targeting Node.js 18 | ||
if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted) { | ||
// TODO: Use ABORT_ERR code when targeting Node.js 16 (https://nodejs.org/docs/latest-v16.x/api/errors.html#abort_err) | ||
throw new AbortError('The task was aborted.'); | ||
} | ||
options.signal?.throwIfAborted(); | ||
let operation = function_({ signal: options.signal }); | ||
if (options.timeout) { | ||
operation = pTimeout(Promise.resolve(operation), options.timeout); | ||
operation = pTimeout(Promise.resolve(operation), { milliseconds: options.timeout }); | ||
} | ||
if (options.signal) { | ||
operation = Promise.race([operation, __classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_throwOnAbort).call(this, options.signal)]); | ||
operation = Promise.race([operation, this.#throwOnAbort(options.signal)]); | ||
} | ||
@@ -134,7 +203,7 @@ const result = await operation; | ||
finally { | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_next).call(this); | ||
this.#next(); | ||
} | ||
}, options); | ||
this.emit('add'); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_tryToStartAnother).call(this); | ||
this.#tryToStartAnother(); | ||
}); | ||
@@ -149,7 +218,7 @@ } | ||
start() { | ||
if (!__classPrivateFieldGet(this, _PQueue_isPaused, "f")) { | ||
if (!this.#isPaused) { | ||
return this; | ||
} | ||
__classPrivateFieldSet(this, _PQueue_isPaused, false, "f"); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_processQueue).call(this); | ||
this.#isPaused = false; | ||
this.#processQueue(); | ||
return this; | ||
@@ -161,3 +230,3 @@ } | ||
pause() { | ||
__classPrivateFieldSet(this, _PQueue_isPaused, true, "f"); | ||
this.#isPaused = true; | ||
} | ||
@@ -168,3 +237,3 @@ /** | ||
clear() { | ||
__classPrivateFieldSet(this, _PQueue_queue, new (__classPrivateFieldGet(this, _PQueue_queueClass, "f"))(), "f"); | ||
this.#queue = new this.#queueClass(); | ||
} | ||
@@ -178,6 +247,6 @@ /** | ||
// Instantly resolve if the queue is empty | ||
if (__classPrivateFieldGet(this, _PQueue_queue, "f").size === 0) { | ||
if (this.#queue.size === 0) { | ||
return; | ||
} | ||
await __classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onEvent).call(this, 'empty'); | ||
await this.#onEvent('empty'); | ||
} | ||
@@ -193,6 +262,6 @@ /** | ||
// Instantly resolve if the queue is empty. | ||
if (__classPrivateFieldGet(this, _PQueue_queue, "f").size < limit) { | ||
if (this.#queue.size < limit) { | ||
return; | ||
} | ||
await __classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onEvent).call(this, 'next', () => __classPrivateFieldGet(this, _PQueue_queue, "f").size < limit); | ||
await this.#onEvent('next', () => this.#queue.size < limit); | ||
} | ||
@@ -206,7 +275,19 @@ /** | ||
// Instantly resolve if none pending and if nothing else is queued | ||
if (__classPrivateFieldGet(this, _PQueue_pending, "f") === 0 && __classPrivateFieldGet(this, _PQueue_queue, "f").size === 0) { | ||
if (this.#pending === 0 && this.#queue.size === 0) { | ||
return; | ||
} | ||
await __classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onEvent).call(this, 'idle'); | ||
await this.#onEvent('idle'); | ||
} | ||
async #onEvent(event, filter) { | ||
return new Promise(resolve => { | ||
const listener = () => { | ||
if (filter && !filter()) { | ||
return; | ||
} | ||
this.off(event, listener); | ||
resolve(); | ||
}; | ||
this.on(event, listener); | ||
}); | ||
} | ||
/** | ||
@@ -216,3 +297,3 @@ Size of the queue, the number of queued items waiting to run. | ||
get size() { | ||
return __classPrivateFieldGet(this, _PQueue_queue, "f").size; | ||
return this.#queue.size; | ||
} | ||
@@ -226,3 +307,3 @@ /** | ||
// eslint-disable-next-line unicorn/no-array-callback-reference | ||
return __classPrivateFieldGet(this, _PQueue_queue, "f").filter(options).length; | ||
return this.#queue.filter(options).length; | ||
} | ||
@@ -233,3 +314,3 @@ /** | ||
get pending() { | ||
return __classPrivateFieldGet(this, _PQueue_pending, "f"); | ||
return this.#pending; | ||
} | ||
@@ -240,106 +321,4 @@ /** | ||
get isPaused() { | ||
return __classPrivateFieldGet(this, _PQueue_isPaused, "f"); | ||
return this.#isPaused; | ||
} | ||
} | ||
_PQueue_carryoverConcurrencyCount = new WeakMap(), _PQueue_isIntervalIgnored = new WeakMap(), _PQueue_intervalCount = new WeakMap(), _PQueue_intervalCap = new WeakMap(), _PQueue_interval = new WeakMap(), _PQueue_intervalEnd = new WeakMap(), _PQueue_intervalId = new WeakMap(), _PQueue_timeoutId = new WeakMap(), _PQueue_queue = new WeakMap(), _PQueue_queueClass = new WeakMap(), _PQueue_pending = new WeakMap(), _PQueue_concurrency = new WeakMap(), _PQueue_isPaused = new WeakMap(), _PQueue_throwOnTimeout = new WeakMap(), _PQueue_instances = new WeakSet(), _PQueue_doesIntervalAllowAnother_get = function _PQueue_doesIntervalAllowAnother_get() { | ||
return __classPrivateFieldGet(this, _PQueue_isIntervalIgnored, "f") || __classPrivateFieldGet(this, _PQueue_intervalCount, "f") < __classPrivateFieldGet(this, _PQueue_intervalCap, "f"); | ||
}, _PQueue_doesConcurrentAllowAnother_get = function _PQueue_doesConcurrentAllowAnother_get() { | ||
return __classPrivateFieldGet(this, _PQueue_pending, "f") < __classPrivateFieldGet(this, _PQueue_concurrency, "f"); | ||
}, _PQueue_next = function _PQueue_next() { | ||
var _a; | ||
__classPrivateFieldSet(this, _PQueue_pending, (_a = __classPrivateFieldGet(this, _PQueue_pending, "f"), _a--, _a), "f"); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_tryToStartAnother).call(this); | ||
this.emit('next'); | ||
}, _PQueue_onResumeInterval = function _PQueue_onResumeInterval() { | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onInterval).call(this); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_initializeIntervalIfNeeded).call(this); | ||
__classPrivateFieldSet(this, _PQueue_timeoutId, undefined, "f"); | ||
}, _PQueue_isIntervalPaused_get = function _PQueue_isIntervalPaused_get() { | ||
const now = Date.now(); | ||
if (__classPrivateFieldGet(this, _PQueue_intervalId, "f") === undefined) { | ||
const delay = __classPrivateFieldGet(this, _PQueue_intervalEnd, "f") - now; | ||
if (delay < 0) { | ||
// Act as the interval was done | ||
// We don't need to resume it here because it will be resumed on line 160 | ||
__classPrivateFieldSet(this, _PQueue_intervalCount, (__classPrivateFieldGet(this, _PQueue_carryoverConcurrencyCount, "f")) ? __classPrivateFieldGet(this, _PQueue_pending, "f") : 0, "f"); | ||
} | ||
else { | ||
// Act as the interval is pending | ||
if (__classPrivateFieldGet(this, _PQueue_timeoutId, "f") === undefined) { | ||
__classPrivateFieldSet(this, _PQueue_timeoutId, setTimeout(() => { | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onResumeInterval).call(this); | ||
}, delay), "f"); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
}, _PQueue_tryToStartAnother = function _PQueue_tryToStartAnother() { | ||
if (__classPrivateFieldGet(this, _PQueue_queue, "f").size === 0) { | ||
// We can clear the interval ("pause") | ||
// Because we can redo it later ("resume") | ||
if (__classPrivateFieldGet(this, _PQueue_intervalId, "f")) { | ||
clearInterval(__classPrivateFieldGet(this, _PQueue_intervalId, "f")); | ||
} | ||
__classPrivateFieldSet(this, _PQueue_intervalId, undefined, "f"); | ||
this.emit('empty'); | ||
if (__classPrivateFieldGet(this, _PQueue_pending, "f") === 0) { | ||
this.emit('idle'); | ||
} | ||
return false; | ||
} | ||
if (!__classPrivateFieldGet(this, _PQueue_isPaused, "f")) { | ||
const canInitializeInterval = !__classPrivateFieldGet(this, _PQueue_instances, "a", _PQueue_isIntervalPaused_get); | ||
if (__classPrivateFieldGet(this, _PQueue_instances, "a", _PQueue_doesIntervalAllowAnother_get) && __classPrivateFieldGet(this, _PQueue_instances, "a", _PQueue_doesConcurrentAllowAnother_get)) { | ||
const job = __classPrivateFieldGet(this, _PQueue_queue, "f").dequeue(); | ||
if (!job) { | ||
return false; | ||
} | ||
this.emit('active'); | ||
job(); | ||
if (canInitializeInterval) { | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_initializeIntervalIfNeeded).call(this); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
}, _PQueue_initializeIntervalIfNeeded = function _PQueue_initializeIntervalIfNeeded() { | ||
if (__classPrivateFieldGet(this, _PQueue_isIntervalIgnored, "f") || __classPrivateFieldGet(this, _PQueue_intervalId, "f") !== undefined) { | ||
return; | ||
} | ||
__classPrivateFieldSet(this, _PQueue_intervalId, setInterval(() => { | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_onInterval).call(this); | ||
}, __classPrivateFieldGet(this, _PQueue_interval, "f")), "f"); | ||
__classPrivateFieldSet(this, _PQueue_intervalEnd, Date.now() + __classPrivateFieldGet(this, _PQueue_interval, "f"), "f"); | ||
}, _PQueue_onInterval = function _PQueue_onInterval() { | ||
if (__classPrivateFieldGet(this, _PQueue_intervalCount, "f") === 0 && __classPrivateFieldGet(this, _PQueue_pending, "f") === 0 && __classPrivateFieldGet(this, _PQueue_intervalId, "f")) { | ||
clearInterval(__classPrivateFieldGet(this, _PQueue_intervalId, "f")); | ||
__classPrivateFieldSet(this, _PQueue_intervalId, undefined, "f"); | ||
} | ||
__classPrivateFieldSet(this, _PQueue_intervalCount, __classPrivateFieldGet(this, _PQueue_carryoverConcurrencyCount, "f") ? __classPrivateFieldGet(this, _PQueue_pending, "f") : 0, "f"); | ||
__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_processQueue).call(this); | ||
}, _PQueue_processQueue = function _PQueue_processQueue() { | ||
// eslint-disable-next-line no-empty | ||
while (__classPrivateFieldGet(this, _PQueue_instances, "m", _PQueue_tryToStartAnother).call(this)) { } | ||
}, _PQueue_throwOnAbort = async function _PQueue_throwOnAbort(signal) { | ||
return new Promise((_resolve, reject) => { | ||
signal.addEventListener('abort', () => { | ||
// TODO: Reject with signal.throwIfAborted() when targeting Node.js 18 | ||
// TODO: Use ABORT_ERR code when targeting Node.js 16 (https://nodejs.org/docs/latest-v16.x/api/errors.html#abort_err) | ||
reject(new AbortError('The task was aborted.')); | ||
}, { once: true }); | ||
}); | ||
}, _PQueue_onEvent = async function _PQueue_onEvent(event, filter) { | ||
return new Promise(resolve => { | ||
const listener = () => { | ||
if (filter && !filter()) { | ||
return; | ||
} | ||
this.off(event, listener); | ||
resolve(); | ||
}; | ||
this.on(event, listener); | ||
}); | ||
}; | ||
export default PQueue; |
@@ -1,3 +0,3 @@ | ||
import { Queue, RunFunction } from './queue.js'; | ||
interface TimeoutOptions { | ||
import { type Queue, type RunFunction } from './queue.js'; | ||
type TimeoutOptions = { | ||
/** | ||
@@ -13,4 +13,4 @@ Per-operation timeout in milliseconds. Operations fulfill once `timeout` elapses if they haven't already. | ||
throwOnTimeout?: boolean; | ||
} | ||
export interface Options<QueueType extends Queue<RunFunction, QueueOptions>, QueueOptions extends QueueAddOptions> extends TimeoutOptions { | ||
}; | ||
export type Options<QueueType extends Queue<RunFunction, QueueOptions>, QueueOptions extends QueueAddOptions> = { | ||
/** | ||
@@ -56,4 +56,4 @@ Concurrency limit. | ||
readonly carryoverConcurrencyCount?: boolean; | ||
} | ||
export interface QueueAddOptions extends TaskOptions, TimeoutOptions { | ||
} & TimeoutOptions; | ||
export type QueueAddOptions = { | ||
/** | ||
@@ -65,4 +65,4 @@ Priority of operation. Operations with greater priority will be scheduled first. | ||
readonly priority?: number; | ||
} | ||
export interface TaskOptions { | ||
} & TaskOptions & TimeoutOptions; | ||
export type TaskOptions = { | ||
/** | ||
@@ -104,3 +104,3 @@ [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) for cancellation of the operation. When aborted, it will be removed from the queue and the `queue.add()` call will reject with an `AbortError`. If the operation is already running, the signal will need to be handled by the operation itself. | ||
readonly signal?: AbortSignal; | ||
} | ||
}; | ||
export {}; |
@@ -1,6 +0,6 @@ | ||
import { Queue, RunFunction } from './queue.js'; | ||
import { QueueAddOptions } from './options.js'; | ||
export interface PriorityQueueOptions extends QueueAddOptions { | ||
import { type Queue, type RunFunction } from './queue.js'; | ||
import { type QueueAddOptions } from './options.js'; | ||
export type PriorityQueueOptions = { | ||
priority?: number; | ||
} | ||
} & QueueAddOptions; | ||
export default class PriorityQueue implements Queue<RunFunction, PriorityQueueOptions> { | ||
@@ -7,0 +7,0 @@ #private; |
@@ -1,12 +0,4 @@ | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _PriorityQueue_queue; | ||
import lowerBound from './lower-bound.js'; | ||
class PriorityQueue { | ||
constructor() { | ||
_PriorityQueue_queue.set(this, []); | ||
} | ||
export default class PriorityQueue { | ||
#queue = []; | ||
enqueue(run, options) { | ||
@@ -21,21 +13,19 @@ options = { | ||
}; | ||
if (this.size && __classPrivateFieldGet(this, _PriorityQueue_queue, "f")[this.size - 1].priority >= options.priority) { | ||
__classPrivateFieldGet(this, _PriorityQueue_queue, "f").push(element); | ||
if (this.size && this.#queue[this.size - 1].priority >= options.priority) { | ||
this.#queue.push(element); | ||
return; | ||
} | ||
const index = lowerBound(__classPrivateFieldGet(this, _PriorityQueue_queue, "f"), element, (a, b) => b.priority - a.priority); | ||
__classPrivateFieldGet(this, _PriorityQueue_queue, "f").splice(index, 0, element); | ||
const index = lowerBound(this.#queue, element, (a, b) => b.priority - a.priority); | ||
this.#queue.splice(index, 0, element); | ||
} | ||
dequeue() { | ||
const item = __classPrivateFieldGet(this, _PriorityQueue_queue, "f").shift(); | ||
return item === null || item === void 0 ? void 0 : item.run; | ||
const item = this.#queue.shift(); | ||
return item?.run; | ||
} | ||
filter(options) { | ||
return __classPrivateFieldGet(this, _PriorityQueue_queue, "f").filter((element) => element.priority === options.priority).map((element) => element.run); | ||
return this.#queue.filter((element) => element.priority === options.priority).map((element) => element.run); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _PriorityQueue_queue, "f").length; | ||
return this.#queue.length; | ||
} | ||
} | ||
_PriorityQueue_queue = new WeakMap(); | ||
export default PriorityQueue; |
export type RunFunction = () => Promise<unknown>; | ||
export interface Queue<Element, Options> { | ||
export type Queue<Element, Options> = { | ||
size: number; | ||
@@ -7,2 +7,2 @@ filter: (options: Partial<Options>) => Element[]; | ||
enqueue: (run: Element, options?: Partial<Options>) => void; | ||
} | ||
}; |
{ | ||
"name": "p-queue", | ||
"version": "7.4.1", | ||
"version": "8.0.0", | ||
"description": "Promise queue with concurrency control", | ||
@@ -9,11 +9,14 @@ "license": "MIT", | ||
"type": "module", | ||
"exports": "./dist/index.js", | ||
"exports": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"sideEffects": false, | ||
"engines": { | ||
"node": ">=12" | ||
"node": ">=18" | ||
}, | ||
"scripts": { | ||
"build": "del-cli dist && tsc", | ||
"//test": "xo && ava && del-cli dist && tsc && tsd", | ||
"test": "ava && del-cli dist && tsc && tsd", | ||
"bench": "node --loader=ts-node/esm bench.ts", | ||
"test": "xo && ava && del-cli dist && tsc && tsd", | ||
"bench": "node --import=tsx/esm bench.ts", | ||
"prepublishOnly": "del-cli dist && tsc" | ||
@@ -49,22 +52,23 @@ }, | ||
"eventemitter3": "^5.0.1", | ||
"p-timeout": "^5.0.2" | ||
"p-timeout": "^6.1.2" | ||
}, | ||
"devDependencies": { | ||
"@sindresorhus/tsconfig": "^2.0.0", | ||
"@types/benchmark": "^2.1.1", | ||
"@types/node": "^17.0.13", | ||
"@sindresorhus/tsconfig": "^5.0.0", | ||
"@types/benchmark": "^2.1.5", | ||
"@types/node": "^20.10.4", | ||
"ava": "^5.3.1", | ||
"benchmark": "^2.1.4", | ||
"del-cli": "^5.0.0", | ||
"delay": "^5.0.0", | ||
"del-cli": "^5.1.0", | ||
"delay": "^6.0.0", | ||
"in-range": "^3.0.0", | ||
"p-defer": "^4.0.0", | ||
"random-int": "^3.0.0", | ||
"time-span": "^5.0.0", | ||
"ts-node": "^10.9.1", | ||
"tsd": "^0.25.0", | ||
"typescript": "^5.2.2", | ||
"xo": "^0.52.0" | ||
"time-span": "^5.1.0", | ||
"tsd": "^0.29.0", | ||
"tsx": "^4.6.2", | ||
"typescript": "^5.3.3", | ||
"xo": "^0.56.0" | ||
}, | ||
"ava": { | ||
"workerThreads": false, | ||
"files": [ | ||
@@ -77,3 +81,3 @@ "test/**" | ||
"nodeArguments": [ | ||
"--loader=ts-node/esm" | ||
"--import=tsx/esm" | ||
] | ||
@@ -80,0 +84,0 @@ }, |
@@ -17,3 +17,3 @@ # p-queue | ||
**Warning:** This package is native [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) and no longer provides a CommonJS export. If your project uses CommonJS, you'll have to [convert to ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) or use the [dynamic `import()`](https://v8.dev/features/dynamic-import) function. Please don't open issues for questions regarding CommonJS / ESM. | ||
**Warning:** This package is native [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) and no longer provides a CommonJS export. If your project uses CommonJS, you'll have to [convert to ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). Please don't open issues for questions regarding CommonJS / ESM. | ||
@@ -143,8 +143,6 @@ ## Usage | ||
*Requires Node.js 16 or later.* | ||
[`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) for cancellation of the operation. When aborted, it will be removed from the queue and the `queue.add()` call will reject with an [error](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/reason). If the operation is already running, the signal will need to be handled by the operation itself. | ||
[`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) for cancellation of the operation. When aborted, it will be removed from the queue and the `queue.add()` call will reject with an `AbortError`. If the operation is already running, the signal will need to be handled by the operation itself. | ||
```js | ||
import PQueue, {AbortError} from 'p-queue'; | ||
import PQueue from 'p-queue'; | ||
import got, {CancelError} from 'got'; | ||
@@ -173,3 +171,3 @@ | ||
} catch (error) { | ||
if (!(error instanceof AbortError)) { | ||
if (!(error instanceof DOMException)) { | ||
throw error; | ||
@@ -384,6 +382,2 @@ } | ||
### AbortError | ||
The error thrown by `queue.add()` when a job is aborted before it is run. See [`signal`](#signal). | ||
## Advanced example | ||
@@ -390,0 +384,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
35972
543
501
+ Addedp-timeout@6.1.2(transitive)
- Removedp-timeout@5.1.0(transitive)
Updatedp-timeout@^6.1.2