UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

107 lines 6.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LoopActivityExecutionStrategy = void 0; const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk"); const ActivityExecutionStrategy_1 = require("./ActivityExecutionStrategy"); class LoopActivityExecutionStrategy extends ActivityExecutionStrategy_1.ActivityExecutionStrategy { get _flowNode() { return this.activityHandler.flowNode; } async execute(startToken) { this.activityHandler.abortSignal.throwIfAborted(); const results = []; let shouldBreak = true; let previousFlowNodeInstanceId = this.activityHandler.previousFlowNodeInstanceId; do { const instanceContext = { currentLoopIndex: results.length, loopResults: results, }; const newActivityInstanceHandler = this.createNewActivityInstanceHandler(previousFlowNodeInstanceId, instanceContext); this.activityInstanceHandlers.push(newActivityInstanceHandler); if (this._maxLoopIterations && this._maxLoopIterations < this.activityInstanceHandlers.length) { const error = new processcube_engine_sdk_1.BadRequestError(`Loop exceeded the maximum allowed amount of iterations: ${this.activityInstanceHandlers.length}/${this._maxLoopIterations}`, 'process'); await newActivityInstanceHandler.persistOnEnter(); await newActivityInstanceHandler.endWithError(error, true); throw error; } const result = await newActivityInstanceHandler.execute(startToken); results.push(result); previousFlowNodeInstanceId = newActivityInstanceHandler.flowNodeInstanceId; shouldBreak = await this.evaluateLoopInstanceBreakCondition(result, results); if (this._timeoutBetweenLoopIterations && !shouldBreak) { await new Promise((resolve) => setTimeout(resolve, this._timeoutBetweenLoopIterations)); } } while (!shouldBreak); return results[results.length - 1]; } async resume(flowNodeInstancesToResume, startToken) { this.activityHandler.abortSignal.throwIfAborted(); const hasNoFlowNodeInstance = !flowNodeInstancesToResume || flowNodeInstancesToResume.length <= 0; if (hasNoFlowNodeInstance) { throw new processcube_engine_sdk_1.InternalServerError('No flowNodeInstances for resuming were supplied.', 'process'); } const results = []; let shouldBreak = true; let previousFlowNodeInstanceId = this.activityHandler.previousFlowNodeInstanceId; const persistedFlowNodeInstances = await this.flowNodeInstanceDatabaseAdapter.loadFlowNodeInstancesForMultiInstance(this.activityHandler.multiInstanceMetadataId); const persistedFlowNodeInstancesWhichAreAlreadyFinished = persistedFlowNodeInstances.filter((fni) => { return fni.state === processcube_engine_sdk_1.FlowNodeInstanceState.finished; }); const persistedFlowNodeInstancesForResuming = persistedFlowNodeInstances.filter((fni) => { return fni.state === processcube_engine_sdk_1.FlowNodeInstanceState.running || fni.state === processcube_engine_sdk_1.FlowNodeInstanceState.suspended; }); for (const fni of persistedFlowNodeInstancesWhichAreAlreadyFinished) { const newActivityInstanceHandler = this.createNewActivityInstanceHandler(fni.previousFlowNodeInstanceId); newActivityInstanceHandler.initFromFlowNodeInstance(fni); this.activityInstanceHandlers.push(newActivityInstanceHandler); } for (const flowNodeInstance of persistedFlowNodeInstancesForResuming) { const newActivityInstanceHandler = this.createNewActivityInstanceHandler(flowNodeInstance.previousFlowNodeInstanceId); this.activityInstanceHandlers.push(newActivityInstanceHandler); const result = await newActivityInstanceHandler.resume(flowNodeInstance); results.push(result); previousFlowNodeInstanceId = newActivityInstanceHandler.flowNodeInstanceId; shouldBreak = await this.evaluateLoopInstanceBreakCondition(result, results); } while (!shouldBreak) { const newActivityInstanceHandler = this.createNewActivityInstanceHandler(previousFlowNodeInstanceId); this.activityInstanceHandlers.push(newActivityInstanceHandler); if (this._maxLoopIterations && this._maxLoopIterations < this.activityInstanceHandlers.length) { const error = new processcube_engine_sdk_1.BadRequestError(`Loop exceeded the maximum allowed amount of iterations: ${this.activityInstanceHandlers.length}/${this._maxLoopIterations}`, 'process'); await newActivityInstanceHandler.persistOnEnter(); await newActivityInstanceHandler.endWithError(error, true); throw error; } if (this._timeoutBetweenLoopIterations) { await new Promise((resolve) => setTimeout(resolve, this._timeoutBetweenLoopIterations)); } const result = await newActivityInstanceHandler.execute(startToken); results.push(result); previousFlowNodeInstanceId = newActivityInstanceHandler.flowNodeInstanceId; shouldBreak = await this.evaluateLoopInstanceBreakCondition(result, results); } return results[results.length - 1]; } async endWithError(error, force = false) { return this.runOnLastFlowNodeInstance((fni) => fni.endWithError(error, force)); } async evaluateLoopInstanceBreakCondition(currentToken, results) { this.activityHandler.abortSignal.throwIfAborted(); const condition = this.activityHandler.flowNode.loopInstanceBreakCondition; const result = await this.processInstance.executeRuntimeExpression({ expression: condition, currentFlowNode: this._flowNode, currentToken: currentToken, previousFlowNode: this.processInstance.getProcessModelFacade().getPreviousFlowNodesFor(this._flowNode)?.pop(), additionalProperties: { currentLoopIndex: results.length, loopResults: results, }, allowNonObjectResults: true, }); return !!result; } } exports.LoopActivityExecutionStrategy = LoopActivityExecutionStrategy; //# sourceMappingURL=LoopActivityExecutionStrategy.js.map