UNPKG

bpmn-elements

Version:

Executable workflow elements based on BPMN 2.0

86 lines (67 loc) 3 kB
import Activity from '../activity/Activity.js'; import { cloneContent } from '../messageHelper.js'; const kCompleted = Symbol.for('completed'); const kTargets = Symbol.for('targets'); export default function EventBasedGateway(activityDef, context) { return new Activity(EventBasedGatewayBehaviour, activityDef, context); } export function EventBasedGatewayBehaviour(activity, context) { this.id = activity.id; this.type = activity.type; this.activity = activity; this.broker = activity.broker; this.context = context; this[kTargets] = new Set(activity.outbound.map((flow) => context.getActivityById(flow.targetId))); } EventBasedGatewayBehaviour.prototype.execute = function execute(executeMessage) { const executeContent = executeMessage.content; const { executionId, outbound = [], outboundTaken } = executeContent; const targets = this[kTargets]; this[kCompleted] = false; if (!targets.size) return this._complete(executeContent); for (const flow of this.activity.outbound) { outbound.push({ id: flow.id, action: 'take' }); } if (!this[kCompleted] && outboundTaken) return; const targetConsumerTag = `_gateway-listener-${this.id}`; const onTargetCompleted = this._onTargetCompleted.bind(this, executeMessage); for (const target of this[kTargets]) { target.broker.subscribeOnce('event', 'activity.end', onTargetCompleted, { consumerTag: targetConsumerTag }); } const broker = this.activity.broker; broker.subscribeOnce('api', `activity.stop.${executionId}`, () => this._stop(), { consumerTag: '_api-stop-execution', }); this[kCompleted] = false; if (!executeMessage.fields.redelivered) { return broker.publish('execution', 'execute.outbound.take', cloneContent(executeContent, { outboundTaken: true })); } }; EventBasedGatewayBehaviour.prototype._onTargetCompleted = function onTargetCompleted(executeMessage, _, message, owner) { const { id: targetId, executionId: targetExecutionId } = message.content; const executeContent = executeMessage.content; const executionId = executeContent.executionId; this.activity.logger.debug(`<${executionId} (${this.id})> <${targetExecutionId}> completed run, discarding the rest`); this._stop(); for (const target of this[kTargets]) { if (target === owner) continue; target.discard(); } const completedContent = cloneContent(executeContent, { taken: { id: targetId, executionId: targetExecutionId, }, ignoreOutbound: true, }); this._complete(completedContent); }; EventBasedGatewayBehaviour.prototype._complete = function complete(completedContent) { this[kCompleted] = true; this.broker.publish('execution', 'execute.completed', cloneContent(completedContent)); }; EventBasedGatewayBehaviour.prototype._stop = function stop() { const targetConsumerTag = `_gateway-listener-${this.id}`; for (const target of this[kTargets]) target.broker.cancel(targetConsumerTag); this.broker.cancel('_api-stop-execution'); };