@zowe/imperative
Version:
framework for building configurable CLIs
133 lines • 5.89 kB
JavaScript
"use strict";
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Queue = void 0;
const constants_1 = require("../../../constants");
const error_1 = require("../../../error");
class Queue {
constructor(options) {
this.defaultQueue = "default";
this.mQueueTimeout = constants_1.Constants.MAX_SIGNED_32BIT_NUMBER;
this.mMaxConcurrentRequests = constants_1.Constants.MAX_SIGNED_32BIT_NUMBER;
this.mQueue = {};
if (options) {
this.setThrottlingOptions(options);
}
this.createQueue();
}
/**
* Changes an existing request queue's throttling options.
* @param options - The throttling options to apply to the request queue.
* @throws {ImperativeError} - when the options provided are out of bounds.
*/
setThrottlingOptions(options) {
// Overwrite the throttling options.
// Timeout changes will only apply to future requests, not ones in progress.
if (options.maxConcurrentRequests != null) {
if (options.maxConcurrentRequests < 0) {
throw new error_1.ImperativeError({ msg: "Maximum concurrent requests cannot be less than zero." });
}
else if (options.maxConcurrentRequests == 0) {
this.mMaxConcurrentRequests = constants_1.Constants.MAX_SIGNED_32BIT_NUMBER;
}
else {
this.mMaxConcurrentRequests = options.maxConcurrentRequests;
}
}
if (options.queueTimeout != null) {
if (options.queueTimeout <= 0 || options.queueTimeout > constants_1.Constants.MAX_SIGNED_32BIT_NUMBER) {
throw new error_1.ImperativeError({ msg: "Queue timeout must be between 0 and " + constants_1.Constants.MAX_SIGNED_32BIT_NUMBER.toString() + "." });
}
this.mQueueTimeout = options.queueTimeout;
}
}
/**
* Add a promise to the queue
* @param promiseFunction The promise, bound with all arguments, to execute on its turn in the queue.
* @param poolId The queue pool that the promise should execute against
* @returns The promise of the promiseFunction
*/
enqueue(promiseFunction, poolId) {
return new Promise((resolve, reject) => {
if (!poolId) {
poolId = this.defaultQueue;
}
// Create and use custom pool if pool is specified.
if (!this.mQueue[poolId]) {
this.createQueue(poolId);
}
// Create the request, and attach the timeout.
const request = {
func: promiseFunction,
timeout: setTimeout(() => { request.timedOut = true; }, this.mQueueTimeout),
timedOut: false,
resolve,
reject
};
// Queue the request and run dequeue.
this.mQueue[poolId].requestPool.push(request);
this.dequeue(poolId);
});
}
/**
* Removes an item from the queue, checks if it times out, and executes the promise if valid
* @param queue The pool of promises to execute against
*/
dequeue(queue) {
return __awaiter(this, void 0, void 0, function* () {
// Exit if there are no more requests in the queue or we are at the maximum number of requests in progress.
if (!this.mQueue[queue].requestPool.length || this.mQueue[queue].inProgress >= this.mMaxConcurrentRequests) {
return;
}
// Get the next item to process, and increment the inProgress counter.
const execItem = this.mQueue[queue].requestPool.shift();
this.mQueue[queue].inProgress++;
try {
clearTimeout(execItem.timeout);
// Try to process the item. If it timed out in the queue, throw an error and pick up the next one.
if (execItem.timedOut) {
throw new error_1.ImperativeError({ msg: "Request timed out while in the request queue." });
}
const result = yield execItem.func();
execItem.resolve(result);
}
catch (err) {
execItem.reject(err);
}
finally {
// Let's go again!
this.mQueue[queue].inProgress--;
this.dequeue(queue);
}
});
}
/**
* Creates a new queue with the provided name. If none is provided, creates a "default" queue/
* @param name The name of the queue to create
*/
createQueue(name = this.defaultQueue) {
if (!this.mQueue[name]) {
this.mQueue[name] = { inProgress: 0, requestPool: [] };
} // Handle check again in case of race condition
}
}
exports.Queue = Queue;
//# sourceMappingURL=Queue.js.map