UNPKG

jest-allure2-reporter

Version:
101 lines 4.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeferredTaskQueue = void 0; class DeferredTaskQueue { pendingPayloads = new Map(); executingTasks = new Map(); processedPayloads = new Set(); config; threadTailPromises = new Map(); constructor(config) { this.config = config; } _getPayloadKey(payload) { return this.config.getPayloadKey(payload); } /** * Starts payload execution, chaining it in its thread and tracking its promise. * @param payload Payload to execute. * @param threadName Thread for this payload. */ _startExecutionAndTrack(payload, threadName) { const payloadKey = this._getPayloadKey(payload); if (this.executingTasks.has(payloadKey)) { return; } const predecessorPromiseInThread = this.threadTailPromises.get(threadName) || Promise.resolve(); const taskExecutor = () => this.config.execute(payload); // Chain the current task to the predecessor in the same thread. // If predecessorPromiseInThread rejects, taskExecutor will not run. const executionChainPromise = predecessorPromiseInThread.then(taskExecutor); // This finalPromise is what gets stored and returned. It includes cleanup. const finalPromise = executionChainPromise.then(() => { this.processedPayloads.add(payloadKey); this.executingTasks.delete(payloadKey); }, () => { this.executingTasks.delete(payloadKey); }); this.executingTasks.set(payloadKey, finalPromise); // This task's promise becomes the new tail for this thread. this.threadTailPromises.set(threadName, finalPromise); } /** * Adds a payload to the queue. * If a payload for the same thread was pending, it starts. The new payload becomes pending. * Does not await started tasks. * @param payload Payload to enqueue. */ enqueue(payload) { const key = this._getPayloadKey(payload); if (this.processedPayloads.has(key)) { // Payload with this key has already been processed, ignore it. return; } const threadName = this.config.getThreadName(payload); const previousPayload = this.pendingPayloads.get(threadName); // Set the new payload as the currently pending one for this thread. this.pendingPayloads.set(threadName, payload); if (previousPayload !== undefined) { // A new payload has superseded `previousPayload` for this thread. // Execute `previousPayload` now. It will be chained correctly by _startExecutionAndTrack. this._startExecutionAndTrack(previousPayload, threadName); } } /** * Starts pending payloads. * If threadName is given, starts tasks for that thread only. Otherwise, starts all pending. * Does not await task completion. * @param threadName Optional. Specific thread to start. */ startPending(threadName) { const payloadsToStart = []; if (threadName) { const payload = this.pendingPayloads.get(threadName); if (payload) { payloadsToStart.push({ payload, threadName }); this.pendingPayloads.delete(threadName); } } else { for (const [tName, payload] of this.pendingPayloads) { payloadsToStart.push({ payload, threadName: tName }); } this.pendingPayloads.clear(); } for (const { payload, threadName: tn } of payloadsToStart) { this._startExecutionAndTrack(payload, tn); } } /** * Waits for all currently executing tasks to complete. * Does not start new tasks. Resolves when all tasks finish (or rejects if any task fails). */ async awaitCompletion() { if (this.executingTasks.size > 0) { const promises = [...this.executingTasks.values()]; await Promise.all(promises); } } } exports.DeferredTaskQueue = DeferredTaskQueue; //# sourceMappingURL=DeferredTaskQueue.js.map