worker-parrot-party
Version:
Parrot party for everyone
98 lines • 4.4 kB
JavaScript
"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