UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

260 lines • 15 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.IntermediateTimerCatchEventHandler = void 0; const async_lock_1 = __importDefault(require("async-lock")); const dayjs_1 = __importDefault(require("dayjs")); const inversify_1 = require("inversify"); const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk"); const index_1 = require("../../../Contracts/index"); const Tools_1 = require("../../../Tools"); const AbortablePromise_1 = require("../../../Tools/AbortablePromise"); const index_2 = require("../../../Tools/DatabaseAdaptersSequelize/index"); const EventMiddlewareHandler_1 = require("../../../Tools/EventMiddlewareHandler"); const TimerFacade_1 = require("../../Facades/TimerFacade"); const ProcessInstance_1 = require("../../ProcessInstance"); const FlowNodeHandlerFactory_1 = require("../FlowNodeHandlerFactory"); const EventHandler_1 = require("./EventHandler"); const lock = new async_lock_1.default({ maxPending: 100000 }); let IntermediateTimerCatchEventHandler = class IntermediateTimerCatchEventHandler extends EventHandler_1.EventHandler { evaluatedTimerExpression; timerFacade; timerSubscription; constructor(eventMiddlewareHandler, flowNodeHandlerFactory, flowNodeInstanceDatabaseAdapter, timerFacade, timerCatchEventModel, processInstance) { super(eventMiddlewareHandler, flowNodeHandlerFactory, flowNodeInstanceDatabaseAdapter, timerCatchEventModel, processInstance, 'timer_catch_event_handler'); this.timerFacade = timerFacade; } get timerCatchEvent() { return this.flowNode; } async persistOnSuspend() { this.abortSignal.signal.throwIfAborted(); let eventName = this.evaluatedTimerExpression; if (typeof this.evaluatedTimerExpression?.toISOString === 'function') { eventName = this.evaluatedTimerExpression.toISOString(); } else if (typeof this.evaluatedTimerExpression != 'string') { eventName = JSON.stringify(this.evaluatedTimerExpression); } await super.persistOnSuspend(undefined, { type: index_1.FlowNodeInstanceDataTypes.catchEvent, eventName: eventName, }); this.publishIntermediateCatchEventReachedNotification(); } async persistOnExit() { await super.persistOnExit(); this.publishIntermediateCatchEventFinishedNotification(); } async persistOnError(error) { await super.persistOnError(error); this.publishIntermediateCatchEventFinishedNotification(); } async persistOnTerminate() { await super.persistOnTerminate(); this.publishIntermediateCatchEventFinishedNotification(); } async startExecution(executionCanceledCallback) { this.abortSignal.signal.throwIfAborted(); this.logger.debug(`Executing TimerCatchEvent instance.`); return this.executeHandler(executionCanceledCallback); } async executeHandler(executionCanceledCallback) { this.abortSignal.signal.throwIfAborted(); return new AbortablePromise_1.AbortablePromise(async (resolve, reject, onCancel) => { if (executionCanceledCallback) { onCancel(() => { if (this.state === processcube_engine_sdk_1.FlowNodeInstanceState.suspended || this.state === processcube_engine_sdk_1.FlowNodeInstanceState.running || this.state === processcube_engine_sdk_1.FlowNodeInstanceState.canceled) { executionCanceledCallback(); } }); } try { this.onInterruptedCallback = () => { this.timerFacade.cancelTimerSubscription(this.timerSubscription); this.abortSignal.abort(); }; this.validateTimer(); await this.suspendAndExecuteTimer(); const canceledByEventBasedGateway = await this.passTriggerThroughEventBasedGatwwayIfNecessary(); if (canceledByEventBasedGateway) { this.cancel(this.processToken); return; } const nextFlowNodeInfo = this.processInstance.getProcessModelFacade().getNextFlowNodesFor(this.timerCatchEvent); return resolve(nextFlowNodeInfo); } catch (error) { return reject(error); } }, { signal: this.abortSignal.signal }); } async resumeAfterSuspend(flowNodeInstance, resumptionCanceledCallback) { this.abortSignal.signal.throwIfAborted(); return new AbortablePromise_1.AbortablePromise(async (resolve, reject, onCancel) => { if (resumptionCanceledCallback) { onCancel(() => { if (this.state === processcube_engine_sdk_1.FlowNodeInstanceState.suspended || this.state === processcube_engine_sdk_1.FlowNodeInstanceState.running || this.state === processcube_engine_sdk_1.FlowNodeInstanceState.canceled) { resumptionCanceledCallback(); } }); } try { this.onInterruptedCallback = () => { this.timerFacade.cancelTimerSubscription(this.timerSubscription); this.abortSignal.abort(); }; this.evaluatedTimerExpression = flowNodeInstance.eventName || (await this.parseTimerValue()); this.publishIntermediateCatchEventReachedNotification(); await this.executeTimer(flowNodeInstance.startedAt); const canceledByEventBasedGateway = await this.passTriggerThroughEventBasedGatwwayIfNecessary(); if (canceledByEventBasedGateway) { this.cancel(this.processToken); return; } const nextFlowNodeInfo = this.processInstance.getProcessModelFacade().getNextFlowNodesFor(this.timerCatchEvent); return resolve(nextFlowNodeInfo); } catch (error) { return reject(error); } }, { signal: this.abortSignal.signal }); } async suspendAndExecuteTimer() { this.abortSignal.signal.throwIfAborted(); this.evaluatedTimerExpression = await this.parseTimerValue(); const waitForTimerPromise = this.executeTimer(); await this.persistOnSuspend(); return waitForTimerPromise; } async executeTimer(timerStartedDate) { this.abortSignal.signal.throwIfAborted(); return new Promise(async (resolve, reject) => { try { const timerElapsed = async () => { this.logger.debug(`Timer on Timer Catch Event Instance ${this.flowNodeInstanceId} expired`, { timerType: this.timerCatchEvent.timerEventDefinition.timerType === processcube_engine_sdk_1.Model.Events.TimerType.timeDate ? 'Date' : 'Duration', timerExpression: this.evaluatedTimerExpression, }); this.timerFacade.cancelTimerSubscription(this.timerSubscription); await this.postEventToEventMiddlewares({ correlationId: this.processInstance.getCorrelationId(), processModelId: this.processInstance.getProcessModelId(), embeddedProcessModelId: this.processInstance.getEmbeddedProcessModelId(), processModelName: this.processInstance.getProcessModelName(), processInstanceId: this.processInstance.getProcessInstanceId(), parentProcessInstanceId: this.processInstance.getParentProcessInstance()?.getProcessInstanceId(), processDefinitionId: this.processInstance.getProcessDefinitionId(), processDefinitionHash: this.processInstance.getProcessDefinitionHash(), flowNodeId: this.flowNode.id, flowNodeName: this.flowNode.name, flowNodeType: this.flowNode.bpmnType, flowNodeLane: this.processInstance.getProcessModelFacade().getLaneForFlowNode(this.flowNode.id)?.name, flowNodeInstanceId: this.flowNodeInstanceId, logLevel: processcube_engine_sdk_1.LogLevel.debug, eventType: processcube_engine_sdk_1.EngineEventType.OnFlowNodeTimerRemoved, tokenPayload: this.processToken, timestamp: dayjs_1.default.utc().toDate(), }); resolve(); }; this.timerSubscription = this.timerFacade.initializeTimer(this.timerCatchEvent.id, this.timerCatchEvent.timerEventDefinition.timerType, this.evaluatedTimerExpression, timerElapsed, this.timerCatchEvent, timerStartedDate); const triggerTimerImmediatelyEvent = index_1.eventAggregatorSettings.messagePaths.triggerTimerEvent.replace(index_1.eventAggregatorSettings.messageParams.flowNodeInstanceId, this.flowNodeInstanceId); Tools_1.EventAggregator.subscribeOnce(triggerTimerImmediatelyEvent, () => { this.timerFacade.triggerTimerImmediately(this.timerSubscription, this.timerCatchEvent.timerEventDefinition.timerType); }); await this.postEventToEventMiddlewares({ correlationId: this.processInstance.getCorrelationId(), processModelId: this.processInstance.getProcessModelId(), embeddedProcessModelId: this.processInstance.getEmbeddedProcessModelId(), processModelName: this.processInstance.getProcessModelName(), processInstanceId: this.processInstance.getProcessInstanceId(), parentProcessInstanceId: this.processInstance.getParentProcessInstance()?.getProcessInstanceId(), processDefinitionId: this.processInstance.getProcessDefinitionId(), processDefinitionHash: this.processInstance.getProcessDefinitionHash(), flowNodeId: this.flowNode.id, flowNodeName: this.flowNode.name, flowNodeType: this.flowNode.bpmnType, flowNodeLane: this.processInstance.getProcessModelFacade().getLaneForFlowNode(this.flowNode.id)?.name, flowNodeInstanceId: this.flowNodeInstanceId, logLevel: processcube_engine_sdk_1.LogLevel.debug, eventType: processcube_engine_sdk_1.EngineEventType.OnFlowNodeTimerStarted, tokenPayload: this.processToken, timestamp: dayjs_1.default.utc().toDate(), }); } catch (error) { reject(error); } }); } validateTimer() { if (!this.timerCatchEvent.timerEventDefinition.timerType || !this.timerCatchEvent.timerEventDefinition.value) { const errorToThrow = new processcube_engine_sdk_1.BadRequestError('Intermediate Timer Catch Event does not have a type or definition assigned.', 'process'); errorToThrow.additionalInformation = { flowNodeInstanceId: this.flowNodeInstanceId, flowNodeId: this.timerCatchEvent.id, flowNodeName: this.timerCatchEvent.name, processInstanceId: this.processInstance.getProcessInstanceId(), processModelId: this.processInstance.getProcessModelId(), embeddedProcessModelId: this.processInstance.getEmbeddedProcessModelId(), correlationId: this.processInstance.getCorrelationId(), }; throw errorToThrow; } } async parseTimerValue() { this.abortSignal.signal.throwIfAborted(); const timerValueExpression = this.timerCatchEvent.timerEventDefinition.value; const doesNotUseRuntimeExpressions = !timerValueExpression || !this.processInstance .getProcessTokenService() .getAvailableParametersForExpressions() .some((param) => timerValueExpression.includes(param)); if (doesNotUseRuntimeExpressions) { return timerValueExpression; } try { return this.processInstance.executeRuntimeExpression({ expression: timerValueExpression, currentFlowNode: this.timerCatchEvent, currentToken: this.processToken, previousFlowNode: this.processInstance.getProcessModelFacade().getPreviousFlowNodesFor(this.timerCatchEvent)?.pop(), allowNonObjectResults: true, }); } catch (err) { err.additionalInformation = { flowNodeInstanceId: this.flowNodeInstanceId, flowNodeType: this.flowNode.bpmnType, flowNodeId: this.flowNode.id, processModelId: this.processInstance.getProcessModelId(), embeddedProcessModelId: this.processInstance.getEmbeddedProcessModelId(), processInstanceId: this.processInstance.getProcessInstanceId(), correlationId: this.processInstance.getCorrelationId(), }; this.logger.error(err); throw err; } } }; exports.IntermediateTimerCatchEventHandler = IntermediateTimerCatchEventHandler; exports.IntermediateTimerCatchEventHandler = IntermediateTimerCatchEventHandler = __decorate([ (0, inversify_1.injectable)(), __metadata("design:paramtypes", [EventMiddlewareHandler_1.EventMiddlewareHandler, FlowNodeHandlerFactory_1.FlowNodeHandlerFactory, index_2.FlowNodeInstanceDatabaseAdapter, TimerFacade_1.TimerFacade, Object, ProcessInstance_1.ProcessInstance]) ], IntermediateTimerCatchEventHandler); //# sourceMappingURL=IntermediateTimerCatchEventHandler.js.map