UNPKG

lugger

Version:

Lugger is an automation framework running on customizable Typescript DSL

354 lines 13.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runWorkflow__ = exports.parallel__ = exports.task__ = exports.step__ = exports.stage__ = exports.StageReflect__ = exports.PipelineCodes = exports.runWorkflow = exports.parallel = exports.task = exports.step = exports.stage = void 0; const ts_basis_1 = require("ts-basis"); const ts_dsl_1 = require("ts-dsl"); const pipeline_model_1 = require("./pipeline.model"); const uuid_1 = require("uuid"); const __1 = require("../../.."); function stage(...args) { return (0, exports.stage__)(...args); } exports.stage = stage; function step(stepName) { return (0, ts_dsl_1.dslIfaceGuard)('step', __filename); } exports.step = step; function task(taskName) { return (0, ts_dsl_1.dslIfaceGuard)('task', __filename); } exports.task = task; function parallelModel(...args) { } class ParallelModel { } ParallelModel.failFast = parallelModel; exports.parallel = parallelModel; function runWorkflow(workflowClass) { return (0, ts_dsl_1.dslIfaceGuard)('runWorkflow', __filename); } exports.runWorkflow = runWorkflow; var PipelineCodesEnum; (function (PipelineCodesEnum) { PipelineCodesEnum[PipelineCodesEnum["PARALLEL_EXEC_FAILURE"] = 0] = "PARALLEL_EXEC_FAILURE"; })(PipelineCodesEnum || (PipelineCodesEnum = {})); exports.PipelineCodes = (0, ts_basis_1.ReturnCodeFamily)('PipelineCodes', PipelineCodesEnum); function getAnonContextname(cce, name) { return `(anonymous_${name}_${cce.blockContext.sourceFile.file.ts.split('/').pop()}:${cce.blockContext.lastRunSource})`; } class StageReflect__ { stage(...args) { } stage_0(stageName, stageClosure) { return null; } ; stage_2(stageOptions) { return null; } stage_3(...args) { return null; } } exports.StageReflect__ = StageReflect__; let _stage_reflect; const stage__ = (...args) => { if (!(0, __1.fromDSL)(args)) { if ((0, ts_dsl_1.isDecorationCall)(args)) { return (0, ts_dsl_1.decoratorHandler)(args, { member: (target, deco) => { deco.addInitializer(function () { const instance = this; addFlowContext(instance, 'stage', deco.name); }); return target; } }); } else if (typeof args[0] === 'string' || args[0].constructor === Object) { const stageOptions = typeof args[0] === 'string' ? { name: args[0] } : args[0]; return (0, ts_dsl_1.decoratorHandler)({ member: (target, deco) => { deco.addInitializer(function () { const instance = this; addFlowContext(instance, 'stage', deco.name); const anyFcb = (0, ts_dsl_1.getRuntime)().functionContextCallbacks.any; const funcPath = `${instance.constructor.name}.${deco.name}`; if (!anyFcb[funcPath]) { anyFcb[funcPath] = []; } anyFcb[funcPath].push(fnCtx => { if (stageOptions) { if (stageOptions.name) { stageOptions.stageName = stageOptions.name; } Object.assign(fnCtx.scopeContext.data, stageOptions); } }); }); return target; } }); } } const cce = args[0]; const a = (0, ts_dsl_1.backfillArgs)(args.slice(1), 'stageOptions', 'stageClosure'); if (typeof a.stageOptions === 'string') { a.stageOptions = { name: a.stageOptions }; } return (0, ts_dsl_1.getRuntime)().scopedExec(cce, 'lugger:pipeline:stage', {}, async (resolve, reject, scopeContext) => { const parentScope = scopeContext.parent; let opts = (parentScope === null || parentScope === void 0 ? void 0 : parentScope.data.stageOptions) ? parentScope === null || parentScope === void 0 ? void 0 : parentScope.data.stageOptions : a.stageOptions; if (!opts) { opts = {}; } if (!opts.name) { opts.name = getAnonContextname(cce, 'stage'); } scopeContext.data.stageName = opts.name; try { if (opts.when) { await (0, ts_dsl_1.punchGrab)(opts.when(parentScope.data.workflowInst)); } let res; if (a.stageClosure) { res = await (0, ts_dsl_1.errorCheck)(a.stageClosure(scopeContext)); } if (!res) { res = {}; } resolve((0, ts_basis_1.ok)(res)); } catch (e) { reject(e); } }); }; exports.stage__ = stage__; exports.stage__.inCollationHandler = ((ica) => { var _a, _b; const a = (0, ts_dsl_1.backfillArgs)(ica.args.slice(1), 'stageOptions', 'stageClosure'); if (typeof a.stageOptions === 'string') { a.stageOptions = { name: a.stageOptions }; } const stageName = ((_a = a.stageOptions) === null || _a === void 0 ? void 0 : _a.name) ? (_b = a.stageOptions) === null || _b === void 0 ? void 0 : _b.name : getAnonContextname(ica.cce, 'stage'); return { collationName: stageName }; }); function step__(cce, ...stepArgs) { const a = (0, ts_dsl_1.backfillArgs)(stepArgs, 'stepName', 'stepClosure'); if (!a.stepName) { a.stepName = getAnonContextname(cce, 'step'); } return (0, ts_dsl_1.getRuntime)().scopedExec(cce, 'lugger:pipeline:step', { data: { stepName: a.stepName }, requireParent: ['lugger:pipeline:stage', 'lugger:pipeline:parallel'] }, async (resolve, reject, scopeContext) => { try { let res; if (a.stepClosure) { res = await (0, ts_dsl_1.errorCheck)(a.stepClosure(scopeContext)); } if (!res) { res = {}; } resolve((0, ts_basis_1.ok)(res)); } catch (e) { reject(e); } }); } exports.step__ = step__; step__.inCollationHandler = ((ica) => { const a = (0, ts_dsl_1.backfillArgs)(ica.args.slice(1), 'stepName', 'stepClosure'); if (!a.stepName) { a.stepName = getAnonContextname(ica.cce, 'step'); } return { collationName: a.stepName }; }); function task__(cce, ...taskArgs) { const a = (0, ts_dsl_1.backfillArgs)(taskArgs, 'taskName', 'taskClosure'); if (!a.taskName) { a.taskName = getAnonContextname(cce, 'task'); } return (0, ts_dsl_1.getRuntime)().scopedExec(cce, 'lugger:pipeline:task', { data: { taskName: a.taskName }, requireParent: ['lugger:pipeline:stage', 'lugger:pipeline:parallel'] }, async (resolve, reject, scopeContext) => { try { let res; if (a.taskClosure) { res = await a.taskClosure(scopeContext); } if (!res) { res = {}; } resolve((0, ts_basis_1.ok)(res)); } catch (e) { reject(e); } }); } exports.task__ = task__; task__.inCollationHandler = ((ica) => { const a = (0, ts_dsl_1.backfillArgs)(ica.args.slice(1), 'taskName', 'taskClosure'); if (!a.taskName) { a.taskName = getAnonContextname(ica.cce, 'step'); } return { collationName: a.taskName }; }); let failFastContext = false; function parallelModel__(cce, ...args) { const collator = new ts_dsl_1.__RuntimeCollator(); const a = (0, ts_dsl_1.backfillArgs)(args, 'parallelOptions', 'collationClosure'); let closureIsCollation = false; if (a.collationClosure && typeof a.collationClosure !== 'function') { closureIsCollation = true; } let options = a.parallelOptions ? a.parallelOptions : { failFast: false }; if (typeof options === 'string') { const optionStr = options; options = { failFast: false }; if (optionStr === 'failFast') { options.failFast = true; } } if (options.failFast === null || options.failFast === undefined) { options.failFast = false; } if (failFastContext) { options.failFast = true; failFastContext = false; } return (0, ts_dsl_1.getRuntime)().scopedExec(cce, 'lugger:pipeline:parallel', { data: { collator } }, async (resolve, reject, scopeContext) => { try { let immediateBlock; scopeContext.onImmediateBlockContextAssign.push((scopeCtx, blockCtx) => { immediateBlock = blockCtx; blockCtx.collator = collator; }); if (closureIsCollation) { collator.collation = a.collationClosure; } else { if (a.collationClosure) { await (0, ts_dsl_1.errorCheck)(a.collationClosure(scopeContext)); } } const proms = []; const collationKeys = Object.keys(collator.collation); for (const key of collationKeys) { proms.push((0, ts_basis_1.promise)(async (resolve, reject) => { try { return resolve(await (0, ts_dsl_1.errorCheck)(collator.collation[key](scopeContext))); } catch (e) { if (options.failFast) { (0, ts_dsl_1.getRuntime)().setScopeError(scopeContext, null, e); } return reject(e); } })); } let res = proms.length ? await ts_basis_1.PromUtil.allSettled(proms) : []; const threadErrors = []; let i = 0; const failedCollationKeys = []; res.forEach(a => { if (a instanceof Error) { const collationKey = collationKeys[i]; threadErrors.push({ key: collationKey, error: a }); failedCollationKeys.push(collationKey); } ++i; }); if (threadErrors.length > 0) { const e = new pipeline_model_1.ParallelExecError(`Parallel exec failed at threads: [${failedCollationKeys.join(', ')}]`); console.log(threadErrors); e.threadErrors = threadErrors; return reject(exports.PipelineCodes.error('PARALLEL_EXEC_FAILURE', e).error); } return resolve(true); } catch (e) { reject(e); } }); } class ParallelModel__ { static failFast(cce, ...args) { return parallelModel__(cce, ...args); } } parallelModel__.failFast = ParallelModel__.failFast; exports.parallel__ = parallelModel__; function runWorkflow__(cce, workflowClass) { return (0, ts_basis_1.promise)(async (resolve, reject) => { const workflowId = (0, uuid_1.v4)(); const wfInst = new workflowClass(); const flowContexts = wfInst.flowContexts; wfInst.__workflowId = workflowId; wfInst.__ctx = cce.scopeContext; const e = { workflow: wfInst, workflowId, workflowName: workflowClass.name, stageName: '', stageType: '', result: null, error: null, rethrow: true, startTime: Date.now(), duration: null, endTime: null, metadata: {}, }; let error; try { if (wfInst['setup']) { await (0, ts_dsl_1.errorCheck)(wfInst['setup'](cce.scopeContext)); } } catch (e) { error = e; } for (const section of flowContexts) { if (error) { break; } try { await (0, ts_dsl_1.errorCheck)(wfInst[section.property](cce.scopeContext)); } catch (e) { error = e; break; } } let postErrors = []; if (!error) { try { if (wfInst['success']) { await (0, ts_dsl_1.errorCheck)(wfInst['success'](cce.scopeContext)); } } catch (e) { postErrors.push(e); } } else { try { if (wfInst['failure']) { await (0, ts_dsl_1.errorCheck)(wfInst['failure'](cce.scopeContext)); } } catch (e) { postErrors.push(e); } } try { if (wfInst['cleanup']) { await (0, ts_dsl_1.errorCheck)(wfInst['cleanup'](cce.scopeContext)); } } catch (e) { postErrors.push(e); } if (error) { return reject(error); } let pipelineReturn; if (wfInst.finalReturn) { pipelineReturn = await (0, ts_dsl_1.punchGrab)(wfInst.finalReturn()); } resolve(pipelineReturn); }); } exports.runWorkflow__ = runWorkflow__; function addFlowContext(workflowInstance, type, property, stageOptions) { if (!workflowInstance.flowContexts) { workflowInstance.flowContexts = []; } workflowInstance.flowContexts.push({ type, class: workflowInstance.constructor, property, stageOptions }); } //# sourceMappingURL=pipeline.js.map