UNPKG

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
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