process-rerun
Version:
The purpose of this library is - build simple and flexible interface for parallel command execution with rerun (on fail) possibility
87 lines • 4.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildExecRunner = buildExecRunner;
/* eslint-disable sonarjs/cognitive-complexity */
const sat_utils_1 = require("sat-utils");
const logger_execution_1 = require("./logger.execution");
const exec_1 = require("./exec");
const logger_1 = require("./logger");
const error_1 = require("./error");
function buildExecRunner(notRetriable, runOpts) {
const { currentExecutionVariable, longestProcessTime, processResultAnalyzer, execOpts = { maxBuffer: 1000 * 1024 }, pollTime, successExitCode = 0, logProcessResult = logger_execution_1.internalLogProcessResult, onExitCloseProcess, onErrorProcess, } = runOpts;
if (!(0, sat_utils_1.isNumber)(successExitCode)) {
throw new error_1.ProcessRerunError('Type', 'successExitCode should be a number');
}
return (cmd, index) => new Promise(resolve => {
const onErrorCloseHandler = null;
const executionHolder = { stackTrace: '' };
/**
* @now this variable will be used for process kill if time more than @longestProcessTime
*/
const startTime = +Date.now();
if (currentExecutionVariable) {
cmd = cmd.includes(currentExecutionVariable)
? cmd.replace(new RegExp(`${currentExecutionVariable}=\\d+`, 'ig'), `${currentExecutionVariable}=${index}`)
: `${currentExecutionVariable}=${index} ${cmd}`;
}
const execProc = (0, exec_1.execute)(cmd, logProcessResult, executionHolder, execOpts);
const killTooLongExecution = (procWhatShouldBeKilled) => {
const executionTime = +Date.now() - startTime;
if (executionTime > longestProcessTime) {
if (executionTime - longestProcessTime > 7500) {
procWhatShouldBeKilled.emit('exit', 100, 'PRO_RERUN_KILL');
procWhatShouldBeKilled.emit('close', 100, 'PRO_RERUN_KILL');
logger_1.logger.error(`Process just marked manually as killed but it is possible that it is still running`);
}
else {
logger_1.logger.info(`Process killed due to long time execution: ${(0, sat_utils_1.millisecondsToMinutes)(executionTime)}\n${cmd}}`);
process.kill(procWhatShouldBeKilled.pid);
}
}
};
const watcher = setInterval(() => killTooLongExecution(execProc), pollTime);
if (onExitCloseProcess) {
execProc.on('exit', (code, signal) => onExitCloseProcess(execProc, code, signal));
}
if (onErrorProcess) {
execProc.on('error', error => onErrorProcess(execProc, error));
}
execProc.on('close', async (code, signal) => {
if (onExitCloseProcess) {
onExitCloseProcess(execProc, code, signal);
}
// clear watcher interval
clearInterval(watcher);
if (onErrorCloseHandler && ((0, sat_utils_1.isFunction)(onErrorCloseHandler) || (0, sat_utils_1.isAsyncFunction)(onErrorCloseHandler))) {
await onErrorCloseHandler();
}
// if process code 0 - exit as a success result
if (code === successExitCode) {
return resolve(null);
}
// processResultAnalyzer - check that stack contains or not contains some specific data
if ((0, sat_utils_1.isFunction)(processResultAnalyzer)) {
const countInNotRetriableBeforeAnalyzation = notRetriable.length;
const analyzationResult = processResultAnalyzer(cmd, executionHolder.stackTrace, notRetriable);
if (!(0, sat_utils_1.isString)(analyzationResult) && !(0, sat_utils_1.isBoolean)(analyzationResult)) {
logger_1.logger.warn('processResultAnalyzer should return boolean or string');
}
// if analyzationResult is string - we want to re-execute command
if ((0, sat_utils_1.isString)(analyzationResult)) {
return resolve(analyzationResult);
}
// if analyzationResult is true - we make assumption that process was finished successfully
if ((0, sat_utils_1.isBoolean)(analyzationResult) && analyzationResult) {
return resolve(null);
}
if (countInNotRetriableBeforeAnalyzation === notRetriable.length ||
((0, sat_utils_1.isBoolean)(analyzationResult) && !analyzationResult)) {
notRetriable.push(cmd);
}
return resolve(null);
}
return resolve(cmd);
});
});
}
//# sourceMappingURL=exec.proc.js.map