UNPKG

worker-parrot-party

Version:
98 lines 4.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PoolParty = void 0; /* eslint-disable max-classes-per-file */ const tslog_1 = require("tslog"); const Parrot_1 = require("./Parrot"); const CustomErrors_1 = require("./CustomErrors"); const ScriptManager_1 = require("./ScriptManager"); class PoolParty { constructor(_poolPartyConfig) { this._poolPartyConfig = _poolPartyConfig; this._logger = new tslog_1.Logger({ name: 'PoolParty' }); this._parrotIdleQueue = []; } async _compileExecutionScripts() { const scriptManager = new ScriptManager_1.ScriptManager(this._poolPartyConfig.compiledFolderName || './worker-script-dist', this._poolPartyConfig.basePath || './'); this._executionScriptFilePath = await scriptManager.createAndCompileExecutionScript(this._poolPartyConfig.task, this._poolPartyConfig.helpers, this._poolPartyConfig.libraryDeclaration); } /** * Function that sapwns the worker parrots based on the configuration size provided. * @param executionFilePath Path to the execution script */ async spawnParrots() { await this._compileExecutionScripts(); while (this._parrotIdleQueue.length < this._poolPartyConfig.partySize) { const parrot = new Parrot_1.Parrot({ execFilePath: this._executionScriptFilePath, resourceLimits: this._poolPartyConfig.resourceLimits, }); this._logger.info(`Spawn parrot [${parrot.pid}]`); this._parrotIdleQueue.push(parrot); } } /** * Function thta returns an idle parrot, if there is no idle, throws a NoIdleParrotError. * @returns {Parrot} */ _getIdleParrot() { const workerParrot = this._parrotIdleQueue.shift(); if (workerParrot) { return workerParrot; } throw new CustomErrors_1.NoIdleParrotError('No idle parrot found'); } /** * Function that Handles Parrot errors and makes sure to spawn a new parrot if the error is not a NoIdleParrotError. * Additionally, kills the parrot instance that caused the error. * * @param parrot Worker parrot instance that throwed the error * @param parrotError Error that was thrown by the parrot */ _handleParrotError(parrot, parrotError) { this._logger.fatal(`Parrot [${parrot.pid}] crashed due to error, spawning new parrot`); this._logger.error(`Error: ${parrotError}`); // Terminates the process to avoid memory leaks parrot.kill(); const recoveryParrot = new Parrot_1.Parrot({ execFilePath: this._executionScriptFilePath, resourceLimits: this._poolPartyConfig.resourceLimits, }); this._logger.info(`Spawn new parrot [${recoveryParrot.pid}]`); this._parrotIdleQueue.push(recoveryParrot); this._poolPartyConfig.onError(parrotError); } /** * * @param args Arguments to be passed to the task function * @returns A Promise that resolves to the result of the task function. Additionally calls the onSuccess function * if provided. If there is an error during the task function execution, calls the onError function if provided. * * Finally, if there are no idle parrots, the task is added to the retry queue and waits until there is an idle parrot. * * Furthermore, when an error occurs and if the error is not identified as a NoIdleParrotError, the onError function is * called, and we spawn a new parrot, since the error causes the parrot to be unavailable for new tasks. */ async run(args) { let parrotExecResult = {}; let parrotWorker; try { parrotWorker = this._getIdleParrot(); parrotExecResult = await parrotWorker.runTask(args); this._poolPartyConfig.onSuccess(parrotExecResult); this._parrotIdleQueue.push(parrotWorker); } catch (parrotError) { const error = parrotError; if (parrotError.type === 'NO_IDLE_PARROT_ERROR') { this._logger.info('No idle parrot found'); } else { this._handleParrotError(parrotWorker, error); } } return parrotExecResult; } } exports.PoolParty = PoolParty; //# sourceMappingURL=PoolParty.js.map