process-rerun
Version:
The purpose of this library is - build simple and flexible interface for parallel command execution with rerun (on fail) possibility
94 lines • 4.14 kB
JavaScript
import { isString, isFunction, isAsyncFunction } from 'sat-utils';
import { buildCommandExecutor } from './command.executor.builder';
import { sleep } from './helpers';
import { logger } from './logger';
import { internalLogStartCycle, internalLogEndCycle, internalLogIntimeCommand } from './logger.execution';
import { addToSharedCache, applySharedCache } from './shared.cache';
const cache = {};
async function intimeExecutor(runOptions, commandsArray) {
const notRetriable = [];
const retriable = [];
let currentSessionCount = 0;
const { attemptsCount, processResultAnalyzer, pollTime, longestProcessTime, killGraceTime, successExitCode, currentExecutionVariable, maxThreads, watcher, logStartCycle = internalLogStartCycle, logEndCycle = internalLogEndCycle, logIntimeCommand = internalLogIntimeCommand, execOpts, sharedCacheVia, } = runOptions;
const executeCommandAsync = buildCommandExecutor(notRetriable, {
currentExecutionVariable,
longestProcessTime,
killGraceTime,
processResultAnalyzer,
pollTime,
successExitCode,
execOpts,
onCache: (published) => addToSharedCache(cache, published),
});
const inTimeCommands = commandsArray.map(cmd => ({
attemptsCount,
cmd,
}));
const inProgressCommands = [];
logStartCycle(maxThreads, attemptsCount, inTimeCommands);
async function runCommand(commands) {
if (maxThreads > currentSessionCount && commands.length) {
currentSessionCount += 1;
let result;
const commadData = commands.splice(0, 1)[0];
const executionIndex = commadData.attemptsCount--;
if (isString(commadData.cmd)) {
// resolve --use-shared-cache against the shared cache (consumes the requested entities)
const cmdToExecute = applySharedCache(cache, commadData.cmd, sharedCacheVia);
const index = inProgressCommands.push(cmdToExecute) - 1;
result = await executeCommandAsync(cmdToExecute, attemptsCount - executionIndex).catch(error => logger.error(error));
inProgressCommands.splice(index, 1);
}
else if (isFunction(commadData.cmd) || isAsyncFunction(commadData.cmd)) {
const index = inProgressCommands.push(commadData.cmd.toString()) - 1;
result = await commadData.cmd(attemptsCount - executionIndex).catch(error => logger.error(error));
inProgressCommands.splice(index, 1);
}
if (result) {
logIntimeCommand(commadData);
commadData.cmd = result;
if (commadData.attemptsCount > 0) {
commands.push(commadData);
}
else {
retriable.push(commadData.cmd);
}
}
currentSessionCount -= 1;
}
}
async function runCommandsArray(commands) {
const initialCommandsCount = commands.length;
const asserter = setInterval(() => runCommand(commands), pollTime);
const watcherRunner = watcher &&
setInterval(() => watcher({
notRetriable: Array.from(notRetriable),
retriable: Array.from(retriable),
inProgressCommands: Array.from(inProgressCommands),
initialCommandsCount,
}), 5000);
do {
if (commands.length) {
await runCommand(commands);
}
if (currentSessionCount) {
await sleep(pollTime);
}
} while (commands.some(({ attemptsCount }) => attemptsCount) ||
currentSessionCount);
clearInterval(asserter);
if (watcherRunner) {
clearInterval(watcherRunner);
}
return commands;
}
const startTime = Date.now();
await runCommandsArray(inTimeCommands);
logEndCycle(retriable, notRetriable, startTime);
return {
retriable,
notRetriable,
};
}
export { intimeExecutor };
//# sourceMappingURL=executor.intime.js.map