UNPKG

@ganache/utils

Version:
129 lines 6.08 kB
"use strict"; 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 __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 _RequestCoordinator_paused, _RequestCoordinator_process; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequestCoordinator = void 0; const noop = () => { }; /** * Responsible for managing global concurrent requests. */ class RequestCoordinator { get paused() { return __classPrivateFieldGet(this, _RequestCoordinator_paused, "f"); } /** * Promise-based FIFO queue. * @param limit - The number of requests that can be processed at a time. * Default value is is no limit (`0`). */ constructor(limit) { /** * The pending requests. You can't do anything with this array. */ this.pending = []; /** * The number of tasks currently being processed. */ this.runningTasks = 0; _RequestCoordinator_paused.set(this, true); /** * Pause processing. This will *not* cancel any promises that are currently * running. */ this.pause = () => { __classPrivateFieldSet(this, _RequestCoordinator_paused, true, "f"); }; /** * Resume processing. */ this.resume = () => { __classPrivateFieldSet(this, _RequestCoordinator_paused, false, "f"); __classPrivateFieldGet(this, _RequestCoordinator_process, "f").call(this); }; _RequestCoordinator_process.set(this, () => { // if we aren't paused and the number of things we're processing is under // our limit and we have things to process: do it! while (!this.paused && this.pending.length > 0 && (!this.limit || this.runningTasks < this.limit)) { const current = this.pending.shift(); this.runningTasks++; current .execute() // By now, we've resolved the fn's `value` by sending it to the parent scope. // But over here, we're also waiting for this fn's _value_ to settle _itself_ (it might be a promise) before // continuing through the `pending` queue. Because we wait for it again here, it could potentially throw here, // in which case we just need to catch it and throw the result away. We could probably use // `Promise.allSettled([current()]).finally` to do this instead of the `current().catch(noop).finally`. /shrug .catch(noop) .finally(() => { this.runningTasks--; __classPrivateFieldGet(this, _RequestCoordinator_process, "f").call(this); }); } }); /** * Insert a new function into the queue. */ this.queue = (fn, thisArgument, argumentsList) => { return new Promise((resolve, reject) => { // const execute is `async` to force the return value into a Promise. const execute = async () => { try { const value = Reflect.apply(fn, thisArgument, argumentsList || []); resolve({ value }); return value; } catch (e) { reject(e); } }; this.pending.push({ execute, reject }); __classPrivateFieldGet(this, _RequestCoordinator_process, "f").call(this); }); }; this.limit = limit; } /** * Stop processing tasks - calls to queue(), and resume() will reject with an * error indicating that Ganache is disconnected. This is an irreversible * action. If you wish to be able to resume processing, use pause() instead. * * Note: this changes the references of this.resume and this.queue. Any code * that maintains references to the values referenced by this.resume or * this.queue, could have unintended consequences after calling this.stop(). */ stop() { this.pause(); this.resume = () => { throw new Error("Cannot resume processing requests, Ganache is disconnected."); }; this.queue = async () => { throw new Error("Cannot process request, Ganache is disconnected."); }; } /** * Finalise shutdown of the RequestCoordinator. Rejects all pending tasks in order. Should be * called after all in-flight tasks have resolved in order to maintain overall FIFO order. */ end() { while (this.pending.length > 0) { this.pending .shift() .reject(new Error("Cannot process request, Ganache is disconnected.")); } } } exports.RequestCoordinator = RequestCoordinator; _RequestCoordinator_paused = new WeakMap(), _RequestCoordinator_process = new WeakMap(); //# sourceMappingURL=request-coordinator.js.map