UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

192 lines • 10.7 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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SignalBoundaryEventHandler = void 0; const inversify_1 = require("inversify"); const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk"); const index_1 = require("../../../Contracts/index"); const index_2 = require("../../../Tools/DatabaseAdaptersSequelize/index"); const EventMiddlewareHandler_1 = require("../../../Tools/EventMiddlewareHandler"); const ProcessInstance_1 = require("../../ProcessInstance"); const SignalEventService_1 = require("../../SignalEventService"); const FlowNodeHandlerFactory_1 = require("../FlowNodeHandlerFactory"); const BoundaryEventHandler_1 = require("./BoundaryEventHandler"); let SignalBoundaryEventHandler = class SignalBoundaryEventHandler extends BoundaryEventHandler_1.BoundaryEventHandler { signalEventService; onSignalSubscriptionId; acknowledgeEventReceivedId; triggerValue; constructor(eventMiddlewareHandler, flowNodeInstanceDatabaseAdapter, flowNodeHandlerFactory, boundaryEventModel, processInstance, processTokenOfAttachedFlowNode, signalEventService) { super(eventMiddlewareHandler, flowNodeInstanceDatabaseAdapter, flowNodeHandlerFactory, boundaryEventModel, processInstance, processTokenOfAttachedFlowNode, 'signal_boundary_event_handler'); this.signalEventService = signalEventService; } async execute(onTriggeredCallback, attachedFlowNodeInstanceId, decoratedFlowNodeRejectFunc) { try { this.logger.debug(`Initializing Signal BoundaryEvent on FlowNodeInstance ${attachedFlowNodeInstanceId}`); await this.parseTriggerValue(); const typeSpecificData = { type: index_1.FlowNodeInstanceDataTypes.catchEvent, eventName: this.boundaryEventModel.signalEventDefinition?.name, triggerValue: this.triggerValue, }; await this.initialize(attachedFlowNodeInstanceId, undefined, typeSpecificData); this.validateSignal(); await this.waitForSignal(onTriggeredCallback, this.boundaryEventModel.signalEventDefinition.name); if (this.boundaryEventModel.cancelActivity) { return this.handleNextFlowNodes(); } } catch (error) { if (this.executionPromise?.controller.signal.aborted) { return; } // persistOnError would fail, if the Boundary>Event Instance was not previously persisted. // This can happen, if running the pre-script fails. // Running "persistOnEnter" again is actually safe, because a repeated call doesn't do anything. await this.persistOnEnter(); await this.persistOnError(error); decoratedFlowNodeRejectFunc(error); } } async resume(boundaryEventInstance, onTriggeredCallback, attachedFlowNodeInstanceId, decoratedFlowNodeRejectFunc, flowNodeInstances) { this.boundaryEventInstance = boundaryEventInstance; this.triggerValue = boundaryEventInstance.triggerValue; this.eventWasTriggered = this.boundaryEventWasTriggered(flowNodeInstances); if (this.eventWasTriggered && this.boundaryEventModel.cancelActivity) { return this.handleNextFlowNodes(flowNodeInstances); } try { await this.initialize(attachedFlowNodeInstanceId, boundaryEventInstance); if (this.boundaryEventInstance?.state === processcube_engine_sdk_1.FlowNodeInstanceState.canceled) { return; } let resumingPromises = []; const executionPromise = this.waitForSignal(onTriggeredCallback, this.boundaryEventModel.signalEventDefinition.name); resumingPromises.push(executionPromise); if (this.eventWasTriggered) { resumingPromises.push(this.handleNextFlowNodes(flowNodeInstances)); } await Promise.all(resumingPromises); } catch (error) { if (this.executionPromise.controller.signal.aborted) { return; } await this.persistOnError(error); decoratedFlowNodeRejectFunc(error); return; } if (this.boundaryEventModel.cancelActivity) { return this.handleNextFlowNodes(); } } async finish() { await super.finish(); this.signalEventService.acknowledge(this.acknowledgeEventReceivedId); this.signalEventService.unsubscribe(this.onSignalSubscriptionId); } async cancel() { this.signalEventService.acknowledge(this.acknowledgeEventReceivedId); this.signalEventService.unsubscribe(this.onSignalSubscriptionId); if (!this.boundaryEventModel.cancelActivity && this.eventWasTriggered) { this.executionFinishCallback?.(); } await super.cancel(); } validateSignal() { if (this.boundaryEventModel.signalEventDefinition?.name === undefined) { const errorToThrow = new processcube_engine_sdk_1.BadRequestError('Signal Boundary Event does not have a signal name assigned.', 'process'); errorToThrow.additionalInformation = { flowNodeInstanceId: this.boundaryEventInstanceId, flowNodeId: this.boundaryEventModel.id, flowNodeName: this.boundaryEventModel.name, processInstanceId: this.processInstance.getProcessInstanceId(), processModelId: this.processInstance.getProcessModelId(), embeddedProcessModelId: this.processInstance.getEmbeddedProcessModelId(), correlationId: this.processInstance.getCorrelationId(), }; throw errorToThrow; } } waitForSignal(onTriggeredCallback, signalName) { this.logger.debug(`Waiting for a "${signalName}" Signal`); this.createExecutionPromise(async (resolve) => { if (!this.boundaryEventModel.cancelActivity) { this.executionFinishCallback = resolve; } const signalReceivedCallback = async (signal) => { this.logger.debug(`SignalBoundaryEvent instance ${this.boundaryEventInstanceId} received signal:`, { receivedMessage: signal, }); this.acknowledgeEventReceivedId = signal.eventId; this.eventWasTriggered = true; this.logger.debug(`SignalBoundaryEvent triggered`); const nextFlowNode = this.getNextFlowNode(); this.processToken = signal?.currentToken ?? {}; await this.runPostScript(); const eventData = { boundaryInstanceId: this.boundaryEventInstanceId, nextFlowNode: nextFlowNode, interruptHandler: this.boundaryEventModel.cancelActivity, eventPayload: this.processToken, canTriggerMultipleTimes: !this.boundaryEventModel.cancelActivity, }; this.triggeredByFlowNodeInstanceId = signal.flowNodeInstanceId; await this.saveTokenInDataObjects(eventData.eventPayload, this.boundaryEventModel.id); this.sendBoundaryEventTriggeredNotification(signalName); onTriggeredCallback(eventData); // An interrupting BoundaryEvent can only be triggered once. // A non-interrupting BoundaryEvent can be triggerred repeatedly. if (this.boundaryEventModel.cancelActivity) { resolve(); } else { this.signalEventService.acknowledge(this.acknowledgeEventReceivedId); this.handleNextFlowNodes(); } }; this.onSignalSubscriptionId = this.signalEventService.onSignal(signalName, signalReceivedCallback, this.boundaryEventModel.cancelActivity, this.processInstance.getProcessInstanceId(), this.triggerValue, this.boundaryEventModel.signalChannel); }); return this.executionPromise.promise; } async parseTriggerValue() { if (!this.boundaryEventModel.triggerValueInToken) { return; } try { this.triggerValue = await this.processInstance.executeRuntimeExpression({ expression: `\`${this.boundaryEventModel.triggerValueInToken}\``, currentFlowNode: this.boundaryEventModel, currentToken: this.processToken, previousFlowNode: this.processInstance.getProcessModelFacade().getPreviousFlowNodesFor(this.boundaryEventModel)?.pop(), allowNonObjectResults: true, }); } catch (error) { const errorToThrow = new processcube_engine_sdk_1.BadRequestError(`SignalBoundaryEvent configuration for setTriggerValueInToken is invalid!`, error.category); errorToThrow.additionalInformation = { setTriggerValueInToken: this.boundaryEventModel.triggerValueInToken, processInstanceId: this.processInstance.getProcessInstanceId(), correlationId: this.processInstance.getCorrelationId(), }; this.logger.error(errorToThrow.message); throw errorToThrow; } } }; exports.SignalBoundaryEventHandler = SignalBoundaryEventHandler; exports.SignalBoundaryEventHandler = SignalBoundaryEventHandler = __decorate([ (0, inversify_1.injectable)(), __metadata("design:paramtypes", [EventMiddlewareHandler_1.EventMiddlewareHandler, index_2.FlowNodeInstanceDatabaseAdapter, FlowNodeHandlerFactory_1.FlowNodeHandlerFactory, Object, ProcessInstance_1.ProcessInstance, Object, SignalEventService_1.SignalEventService]) ], SignalBoundaryEventHandler); //# sourceMappingURL=SignalBoundaryEventHandler.js.map