const Waterfall = require('./waterfall') /** * Executes operations sequentially. * Has an option for a buffer that can be triggered afterwards. * @private */ class Executor { /** * Instantiates a new Executor. */ constructor () { /** * If this.ready is `false`, then every task pushed will be buffered until this.processBuffer is called. * @type {boolean} * @private */ this.ready = false /** * The main queue * @type {Waterfall} * @private */ this.queue = new Waterfall() /** * The buffer queue * @type {Waterfall} * @private */ this.buffer = null /** * Method to trigger the buffer processing. * * Do not be use directly, use `this.processBuffer` instead. * @function * @private */ this._triggerBuffer = null this.resetBuffer() } /** * If executor is ready, queue task (and process it immediately if executor was idle) * If not, buffer task for later processing * @param {AsyncFunction} task Function to execute * @param {boolean} [forceQueuing = false] Optional (defaults to false) force executor to queue task even if it is not ready * @return {Promise<*>} * @async * @see Executor#push */ pushAsync (task, forceQueuing = false) { if (this.ready || forceQueuing) return this.queue.waterfall(task)() else return this.buffer.waterfall(task)() } /** * Queue all tasks in buffer (in the same order they came in) * Automatically sets executor as ready */ processBuffer () { this.ready = true this._triggerBuffer() this.queue.waterfall(() => this.buffer.guardian) } /** * Removes all tasks queued up in the buffer */ resetBuffer () { this.buffer = new Waterfall() this.buffer.chain(new Promise(resolve => { this._triggerBuffer = resolve })) if (this.ready) this._triggerBuffer() } } // Interface module.exports = Executor