UNPKG

azurite

Version:

An open source Azure Storage API compatible server

89 lines 3.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = require("events"); const uuid = require("uuid"); class OperationQueue { constructor(maxConcurrency, logger) { this.maxConcurrency = maxConcurrency; this.logger = logger; this.operations = []; this.runningConcurrency = 0; this.emitter = new events_1.EventEmitter(); } /** * Add an operation to be executed. * * @template T * @param {Promise<T>} op * @param {string} [contextId] * @returns {Promise<T>} * @memberof OperationQueue */ async operate(op, contextId) { const id = uuid(); this.operations.push({ id, op }); this.logger.debug(`OperationQueue.operate() Schedule incoming job ${id}`, contextId); this.execute(contextId); return new Promise((resolve, reject) => { this.emitter .once(id, res => { this.logger.debug(`OperationQueue.operate() Job ${id} completes callback, resolve.`, contextId); this.emitter.removeAllListeners("error_" + id); resolve(res); process.nextTick(() => { this.execute(contextId); }); }) .once("error_" + id, err => { this.logger.debug(`OperationQueue.operate() Job ${id} error, reject.`, contextId); this.emitter.removeAllListeners(id); reject(err); process.nextTick(() => { this.execute(contextId); }); }); }); } /** * It assists queue to execute the operation. * * @private * @param {string} [contextId] * @returns * @memberof OperationQueue */ async execute(contextId) { this.logger.debug(`OperationQueue:execute() Current runningConcurrency:${this.runningConcurrency} maxConcurrency:${this.maxConcurrency} operations.length:${this.operations.length}`, contextId); if (this.runningConcurrency < this.maxConcurrency) { if (this.operations.length === 0) { this.logger.debug(`OperationQueue:execute() return. Operation.length === 0`, contextId); return; } this.runningConcurrency++; const head = this.operations.shift(); let res; try { // this.logger.debug(`OperationQueue:execute() await ${head!.id}`); res = await head.op(); // this.logger.debug(`OperationQueue:execute() ${head!.id} done`); } catch (err) { this.runningConcurrency--; // this.logger.debug( // `OperationQueue:execute() ${head!.id} emit error ${err}` // ); this.emitter.emit(`error_${head.id}`, err); return; } this.runningConcurrency--; // this.logger.debug( // `OperationQueue:execute() emit ${head!.id}. runningConcurrency: ${ // this.runningConcurrency // }` // ); this.emitter.emit(head.id, res); } } } exports.default = OperationQueue; //# sourceMappingURL=OperationQueue.js.map