UNPKG

node-apparatus

Version:

A mix of common components needed for awesome node experience

91 lines 3.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SequentialInvocationQueue = void 0; const spin_wait_lock_1 = require("../spin-wait-lock/spin-wait-lock"); /** * A class that allows for the sequential invocation of a function. */ class SequentialInvocationQueue { /** * @param lock The lock to used for synchronization. * @param invocationFunction The function to invoke. * @param maxQueueLength The maximum length of the queue. */ constructor(lock = new spin_wait_lock_1.SpinWaitLock(), invocationFunction, maxQueueLength = Number.MAX_SAFE_INTEGER) { this.lock = lock; this.invocationFunction = invocationFunction; this.maxQueueLength = maxQueueLength; this.invocationQueue = new Array(); } /** * Invokes the function with the given arguments, if an execution is already underway en-ques the current invocation. * @param args The arguments to pass to the invocationFunction. * @param spinTime The time to wait between attempts to acquire the lock. * @param index The index to replace in the queue, if an execution is already active. * @returns A promise that resolves to the result of the invocation. */ async invoke(args, spinTime = 100, index = undefined) { if (this.invocationQueue.length >= this.maxQueueLength) return { state: "error:queue-full" }; if (index !== undefined) { this.invocationQueue[index] = args; } else { this.invocationQueue.push(args); } try { const lockResult = await this.lock.acquire(spinTime, () => this.invocationQueue.length <= 0); if (lockResult === spin_wait_lock_1.SpinWaitLockState.Condition) { return { state: "error:queue-empty" }; } else { if (this.invocationQueue.length === 0) return { state: "error:queue-empty" }; const invocationParams = this.invocationQueue.shift(); const result = await this.invocationFunction(invocationParams); return { result, state: "success" }; } } finally { this.lock.release(); } } /** * Deletes the invocation at the given index. * @param index The index of the invocation to delete. * @returns void */ delete(index) { this.invocationQueue.splice(index, 1); } /** * Returns an iterator for the invocation queue. * @returns An iterator for the invocation queue. * @example * ```typescript * const invocationQueue = new SequentialInvocationQueue<number[], void>(new SpinWaitLock(), sensitiveWork); * invocationQueue.invoke([undefined, 0]); * invocationQueue.invoke([undefined, 1]); * invocationQueue.invoke([undefined, 2]); * for (const invocation of invocationQueue) { * console.log(invocation); * } * ``` */ [Symbol.iterator]() { return this.invocationQueue[Symbol.iterator](); } /** * Clears the invocation queue. * @returns void */ clear() { this.invocationQueue.length = 0; } [Symbol.asyncDispose]() { this.invocationQueue.length = 0; this.lock.release(); } } exports.SequentialInvocationQueue = SequentialInvocationQueue; //# sourceMappingURL=sequential-invocation-queue.js.map