@5minds/processcube_engine
Version:
The ProcessCube Engine. Stores and executes BPMNs.
107 lines • 6.57 kB
JavaScript
"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