bpmn-elements 9.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/dist/EventBroker.js +4 -0
  4. package/dist/Tracker.js +89 -0
  5. package/dist/activity/Activity.js +47 -57
  6. package/dist/activity/ActivityExecution.js +6 -9
  7. package/dist/definition/Definition.js +23 -17
  8. package/dist/definition/DefinitionExecution.js +23 -0
  9. package/dist/eventDefinitions/CancelEventDefinition.js +20 -76
  10. package/dist/eventDefinitions/CompensateEventDefinition.js +54 -41
  11. package/dist/eventDefinitions/ConditionalEventDefinition.js +11 -2
  12. package/dist/eventDefinitions/ErrorEventDefinition.js +2 -0
  13. package/dist/events/BoundaryEvent.js +25 -10
  14. package/dist/flows/Association.js +0 -7
  15. package/dist/gateways/EventBasedGateway.js +1 -2
  16. package/dist/process/Process.js +5 -0
  17. package/dist/process/ProcessExecution.js +128 -36
  18. package/dist/tasks/SubProcess.js +2 -1
  19. package/package.json +4 -4
  20. package/src/EventBroker.js +1 -0
  21. package/src/Tracker.js +73 -0
  22. package/src/activity/Activity.js +45 -51
  23. package/src/activity/ActivityExecution.js +6 -8
  24. package/src/definition/Definition.js +24 -21
  25. package/src/definition/DefinitionExecution.js +26 -0
  26. package/src/eventDefinitions/CancelEventDefinition.js +22 -66
  27. package/src/eventDefinitions/CompensateEventDefinition.js +48 -40
  28. package/src/eventDefinitions/ConditionalEventDefinition.js +12 -2
  29. package/src/eventDefinitions/ErrorEventDefinition.js +2 -0
  30. package/src/events/BoundaryEvent.js +20 -8
  31. package/src/flows/Association.js +0 -10
  32. package/src/gateways/EventBasedGateway.js +1 -2
  33. package/src/process/Process.js +6 -0
  34. package/src/process/ProcessExecution.js +126 -36
  35. package/src/tasks/SubProcess.js +2 -1
  36. package/types/index.d.ts +29 -0
@@ -191,10 +191,11 @@ SubProcessBehaviour.prototype._onExecutionCompleted = function onExecutionComple
191
191
  broker.cancel(message.fields.consumerTag);
192
192
  break;
193
193
  }
194
+ case 'cancel':
194
195
  case 'discard':
195
196
  {
196
197
  broker.cancel(message.fields.consumerTag);
197
- broker.publish('execution', 'execute.discard', (0, _messageHelper.cloneContent)(content));
198
+ broker.publish('execution', 'execute.' + messageType, (0, _messageHelper.cloneContent)(content));
198
199
  break;
199
200
  }
200
201
  case 'completed':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmn-elements",
3
- "version": "9.0.0",
3
+ "version": "9.1.0",
4
4
  "description": "Executable workflow elements based on BPMN 2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -46,8 +46,8 @@
46
46
  "devDependencies": {
47
47
  "@aircall/expression-parser": "^1.0.4",
48
48
  "@babel/cli": "^7.21.0",
49
- "@babel/core": "^7.21.3",
50
- "@babel/preset-env": "^7.20.2",
49
+ "@babel/core": "^7.21.4",
50
+ "@babel/preset-env": "^7.21.4",
51
51
  "@babel/register": "^7.21.0",
52
52
  "bpmn-moddle": "^8.0.1",
53
53
  "c8": "^7.13.0",
@@ -55,7 +55,7 @@
55
55
  "chai": "^4.3.7",
56
56
  "chronokinesis": "^4.0.1",
57
57
  "debug": "^4.3.4",
58
- "eslint": "^8.36.0",
58
+ "eslint": "^8.37.0",
59
59
  "eslint-plugin-import": "^2.27.5",
60
60
  "got": "^12.6.0",
61
61
  "mocha": "^10.1.0",
@@ -48,6 +48,7 @@ function ExecutionBroker(brokerOwner, prefix, onBrokerReturn) {
48
48
  const runQ = broker.assertQueue('run-q', {durable: true, autoDelete: false});
49
49
  const formatRunQ = broker.assertQueue('format-run-q', {durable: true, autoDelete: false});
50
50
  const executionQ = broker.assertQueue('execution-q', {durable: true, autoDelete: false});
51
+ broker.assertQueue('inbound-q', {durable: true, autoDelete: false});
51
52
 
52
53
  broker.bindQueue(runQ.name, 'run', 'run.#');
53
54
  broker.bindQueue(formatRunQ.name, 'format', 'run.#');
package/src/Tracker.js ADDED
@@ -0,0 +1,73 @@
1
+ export function ActivityTracker(parentId) {
2
+ this.id = parentId;
3
+ this.status = { wait: [], execute: [], timer: [] };
4
+ }
5
+
6
+ Object.defineProperty(ActivityTracker.prototype, 'activityStatus', {
7
+ get() {
8
+ const status = this.status;
9
+ if (status.execute.length) return 'executing';
10
+ if (status.timer.length) return 'timer';
11
+ return status.wait.length ? 'wait' : 'idle';
12
+ },
13
+ });
14
+
15
+ ActivityTracker.prototype.track = function track(routingKey, message) {
16
+ const content = message.content;
17
+ if (content.isSequenceFlow) return;
18
+ if (content.isSubProcess) return;
19
+ const executionId = content.executionId;
20
+
21
+ switch (routingKey) {
22
+ case 'activity.enter':
23
+ case 'activity.discard':
24
+ case 'activity.start':
25
+ case 'activity.execution.completed':
26
+ case 'activity.execution.error':
27
+ case 'activity.end':
28
+ this._executing(executionId);
29
+ break;
30
+ case 'activity.execution.outbound.take':
31
+ case 'activity.detach':
32
+ case 'activity.wait': {
33
+ if (content.isMultiInstance) this._waiting(content.parent.executionId);
34
+ else this._waiting(executionId);
35
+ break;
36
+ }
37
+ case 'activity.timer':
38
+ this._timer(content.parent.executionId);
39
+ break;
40
+ case 'activity.leave':
41
+ this._leave(executionId);
42
+ break;
43
+ }
44
+ };
45
+
46
+ ActivityTracker.prototype._executing = function executing(id) {
47
+ const {wait, execute} = this.status;
48
+ if (execute.indexOf(id) === -1) execute.push(id);
49
+ let idx;
50
+ if ((idx = wait.indexOf(id)) !== -1) wait.splice(idx, 1);
51
+ };
52
+
53
+ ActivityTracker.prototype._waiting = function waiting(id) {
54
+ const {wait, execute} = this.status;
55
+ if (wait.indexOf(id) === -1) wait.push(id);
56
+ let idx;
57
+ if ((idx = execute.indexOf(id)) !== -1) execute.splice(idx, 1);
58
+ };
59
+
60
+ ActivityTracker.prototype._timer = function timerFn(id) {
61
+ const {timer, execute} = this.status;
62
+ if (timer.indexOf(id) === -1) timer.push(id);
63
+ let idx;
64
+ if ((idx = execute.indexOf(id)) !== -1) execute.splice(idx, 1);
65
+ };
66
+
67
+ ActivityTracker.prototype._leave = function leave(id) {
68
+ const {wait, execute, timer} = this.status;
69
+ let idx;
70
+ if ((idx = wait.indexOf(id)) !== -1) wait.splice(idx, 1);
71
+ if ((idx = execute.indexOf(id)) !== -1) execute.splice(idx, 1);
72
+ if ((idx = timer.indexOf(id)) !== -1) timer.splice(idx, 1);
73
+ };
@@ -1,5 +1,5 @@
1
1
  import ActivityExecution from './ActivityExecution.js';
2
- import {brokerSafeId, getUniqueId} from '../shared.js';
2
+ import {getUniqueId} from '../shared.js';
3
3
  import {ActivityApi} from '../Api.js';
4
4
  import {ActivityBroker} from '../EventBroker.js';
5
5
  import {Formatter} from '../MessageFormatter.js';
@@ -18,6 +18,7 @@ const kFlows = Symbol.for('flows');
18
18
  const kFormatter = Symbol.for('formatter');
19
19
  const kMessageHandlers = Symbol.for('messageHandlers');
20
20
  const kStateMessage = Symbol.for('stateMessage');
21
+ const kActivated = Symbol.for('activated');
21
22
 
22
23
  export default Activity;
23
24
 
@@ -39,6 +40,7 @@ function Activity(Behaviour, activityDef, context) {
39
40
  taken: 0,
40
41
  discarded: 0,
41
42
  };
43
+ const isForCompensation = !!behaviour.isForCompensation;
42
44
 
43
45
  let attachedToActivity, attachedTo;
44
46
  if (attachedToRef) {
@@ -56,7 +58,14 @@ function Activity(Behaviour, activityDef, context) {
56
58
 
57
59
  const inboundSequenceFlows = context.getInboundSequenceFlows(id);
58
60
  const inboundAssociations = context.getInboundAssociations(id);
59
- const inboundTriggers = attachedToActivity ? [attachedToActivity] : inboundSequenceFlows.slice();
61
+ let inboundTriggers;
62
+ if (attachedToActivity) {
63
+ inboundTriggers = [attachedToActivity];
64
+ } else if (isForCompensation) {
65
+ inboundTriggers = inboundAssociations.slice();
66
+ } else {
67
+ inboundTriggers = inboundSequenceFlows.slice();
68
+ }
60
69
  const outboundSequenceFlows = context.getOutboundSequenceFlows(id);
61
70
  const flows = this[kFlows] = {
62
71
  inboundSequenceFlows,
@@ -67,7 +76,6 @@ function Activity(Behaviour, activityDef, context) {
67
76
  outboundEvaluator: new OutboundEvaluator(this, outboundSequenceFlows),
68
77
  };
69
78
 
70
- const isForCompensation = !!behaviour.isForCompensation;
71
79
  const isParallelJoin = activityDef.isParallelGateway && flows.inboundSequenceFlows.length > 1;
72
80
  this[kFlags] = {
73
81
  isEnd: flows.outboundSequenceFlows.length === 0,
@@ -89,19 +97,6 @@ function Activity(Behaviour, activityDef, context) {
89
97
  onExecutionMessage: this._onExecutionMessage.bind(this),
90
98
  };
91
99
 
92
- const onInboundEvent = this._onInboundEvent.bind(this);
93
- broker.assertQueue('inbound-q', {durable: true, autoDelete: false});
94
- if (isForCompensation) {
95
- for (const trigger of inboundAssociations) {
96
- trigger.broker.subscribeTmp('event', '#', onInboundEvent, {noAck: true, consumerTag: `_inbound-${id}`});
97
- }
98
- } else {
99
- for (const trigger of inboundTriggers) {
100
- if (trigger.isSequenceFlow) trigger.broker.subscribeTmp('event', 'flow.#', onInboundEvent, {noAck: true, consumerTag: `_inbound-${id}`});
101
- else trigger.broker.subscribeTmp('event', 'activity.#', onInboundEvent, {noAck: true, consumerTag: `_inbound-${id}`});
102
- }
103
- }
104
-
105
100
  this[kEventDefinitions] = eventDefinitions && eventDefinitions.map((ed) => new ed.Behaviour(this, ed, this.context));
106
101
  this[kExtensions] = context.loadExtensions(this);
107
102
  }
@@ -198,6 +193,12 @@ Object.defineProperty(Activity.prototype, 'isSubProcess', {
198
193
  return this[kFlags].isSubProcess;
199
194
  },
200
195
  });
196
+ Object.defineProperty(Activity.prototype, 'isTransaction', {
197
+ enumerable: true,
198
+ get() {
199
+ return this[kFlags].isTransaction;
200
+ },
201
+ });
201
202
 
202
203
  Object.defineProperty(Activity.prototype, 'isMultiInstance', {
203
204
  enumerable: true,
@@ -242,12 +243,15 @@ Object.defineProperty(Activity.prototype, 'eventDefinitions', {
242
243
  });
243
244
 
244
245
  Activity.prototype.activate = function activate() {
245
- if (this[kFlags].isForCompensation) return;
246
+ this[kActivated] = true;
247
+ this.addInboundListeners();
246
248
  return this._consumeInbound();
247
249
  };
248
250
 
249
251
  Activity.prototype.deactivate = function deactivate() {
252
+ this[kActivated] = false;
250
253
  const broker = this.broker;
254
+ this.removeInboundListeners();
251
255
  broker.cancel('_run-on-inbound');
252
256
  broker.cancel('_format-consumer');
253
257
  };
@@ -326,9 +330,26 @@ Activity.prototype.discard = function discard(discardContent) {
326
330
  this._consumeRunQ();
327
331
  };
328
332
 
333
+ Activity.prototype.addInboundListeners = function addInboundListeners() {
334
+ const onInboundEvent = this._onInboundEvent.bind(this);
335
+ const triggerConsumerTag = `_inbound-${this.id}`;
336
+ for (const trigger of this[kFlows].inboundTriggers) {
337
+ if (trigger.isSequenceFlow) trigger.broker.subscribeTmp('event', 'flow.#', onInboundEvent, {noAck: true, consumerTag: triggerConsumerTag});
338
+ else if (this.isForCompensation) trigger.broker.subscribeTmp('event', 'association.#', onInboundEvent, {noAck: true, consumerTag: triggerConsumerTag});
339
+ else trigger.broker.subscribeTmp('event', 'activity.#', onInboundEvent, {noAck: true, consumerTag: triggerConsumerTag});
340
+ }
341
+ };
342
+
343
+ Activity.prototype.removeInboundListeners = function removeInboundListeners() {
344
+ const triggerConsumerTag = `_inbound-${this.id}`;
345
+ for (const trigger of this[kFlows].inboundTriggers) {
346
+ trigger.broker.cancel(triggerConsumerTag);
347
+ }
348
+ };
349
+
329
350
  Activity.prototype.stop = function stop() {
330
- if (!this[kConsuming]) return;
331
- return this.getApi().stop();
351
+ if (!this[kConsuming]) return this.broker.cancel('_run-on-inbound');
352
+ return this.getApi(this[kStateMessage]).stop();
332
353
  };
333
354
 
334
355
  Activity.prototype.next = function next() {
@@ -394,6 +415,7 @@ Activity.prototype._discardRun = function discardRun() {
394
415
 
395
416
  const execution = this[kExec].execution;
396
417
  if (execution && !execution.completed) return;
418
+
397
419
  switch (status) {
398
420
  case 'executing':
399
421
  case 'error':
@@ -427,6 +449,8 @@ Activity.prototype._shakeOutbound = function shakeOutbound(sourceMessage) {
427
449
  };
428
450
 
429
451
  Activity.prototype._consumeInbound = function consumeInbound() {
452
+ if (!this[kActivated]) return;
453
+
430
454
  if (this.status) return;
431
455
  const inboundQ = this.broker.getQueue('inbound-q');
432
456
  if (this[kFlags].isParallelJoin) {
@@ -438,7 +462,6 @@ Activity.prototype._consumeInbound = function consumeInbound() {
438
462
 
439
463
  Activity.prototype._onInbound = function onInbound(routingKey, message) {
440
464
  message.ack();
441
- const id = this.id;
442
465
  const broker = this.broker;
443
466
  broker.cancel('_run-on-inbound');
444
467
 
@@ -460,16 +483,6 @@ Activity.prototype._onInbound = function onInbound(routingKey, message) {
460
483
  if (content.discardSequence) discardSequence = content.discardSequence.slice();
461
484
  return this._runDiscard({inbound, discardSequence});
462
485
  }
463
- case 'association.complete': {
464
- broker.cancel('_run-on-inbound');
465
-
466
- const compensationId = `${brokerSafeId(id)}_${brokerSafeId(content.sequenceId)}`;
467
- this.logger.debug(`<${id}> completed compensation with id <${compensationId}>`);
468
-
469
- return this._publishEvent('compensation.end', this._createMessage({
470
- executionId: compensationId,
471
- }));
472
- }
473
486
  }
474
487
  };
475
488
 
@@ -516,7 +529,6 @@ Activity.prototype._onJoinInbound = function onJoinInbound(routingKey, message)
516
529
 
517
530
  Activity.prototype._onInboundEvent = function onInboundEvent(routingKey, message) {
518
531
  const {fields, content, properties} = message;
519
- const id = this.id;
520
532
  const inboundQ = this.broker.getQueue('inbound-q');
521
533
 
522
534
  switch (routingKey) {
@@ -534,25 +546,6 @@ Activity.prototype._onInboundEvent = function onInboundEvent(routingKey, message
534
546
  case 'flow.take':
535
547
  case 'flow.discard':
536
548
  return inboundQ.queueMessage(fields, cloneContent(content), properties);
537
- case 'association.discard': {
538
- this.logger.debug(`<${id}> compensation discarded`);
539
- return inboundQ.purge();
540
- }
541
- case 'association.complete': {
542
- if (!this[kFlags].isForCompensation) break;
543
-
544
- inboundQ.queueMessage(fields, cloneContent(content), properties);
545
-
546
- const compensationId = `${brokerSafeId(id)}_${brokerSafeId(content.sequenceId)}`;
547
- this._publishEvent('compensation.start', this._createMessage({
548
- executionId: compensationId,
549
- placeholder: true,
550
- }));
551
-
552
- this.logger.debug(`<${id}> start compensation with id <${compensationId}>`);
553
-
554
- return this._consumeInbound();
555
- }
556
549
  }
557
550
  };
558
551
 
@@ -631,6 +624,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
631
624
  case 'run.execute.passthrough': {
632
625
  const execution = this.execution;
633
626
  if (!isRedelivered && execution) {
627
+ if (execution.completed) return message.ack();
634
628
  this[kExecuteMessage] = message;
635
629
  return execution.passthrough(message);
636
630
  }
@@ -739,6 +733,7 @@ Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey,
739
733
  broker.publish('run', 'run.discarded', content, {correlationId});
740
734
  break;
741
735
  }
736
+ case 'execution.cancel':
742
737
  case 'execution.discard':
743
738
  this.status = 'discarded';
744
739
  broker.publish('run', 'run.discarded', content, {correlationId});
@@ -756,7 +751,6 @@ Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey,
756
751
  Activity.prototype._ackRunExecuteMessage = function ackRunExecuteMessage() {
757
752
  if (this.environment.settings.step) return;
758
753
  const executeMessage = this[kExecuteMessage];
759
- this[kExecuteMessage] = null;
760
754
  executeMessage.ack();
761
755
  };
762
756
 
@@ -178,10 +178,12 @@ ActivityExecution.prototype._onExecuteMessage = function onExecuteMessage(routin
178
178
  if (!this[kPostponed].length) return this.broker.publish('execution', 'execute.start', cloneContent(this[kExecuteMessage].content));
179
179
  break;
180
180
  }
181
+ case 'execute.cancel':
182
+ return this._onExecutionDiscarded('cancel', message);
181
183
  case 'execute.error':
184
+ return this._onExecutionDiscarded('error', message);
182
185
  case 'execute.discard':
183
- return this._onExecutionDiscarded(message);
184
- case 'execute.cancel':
186
+ return this._onExecutionDiscarded('discard', message);
185
187
  case 'execute.completed': {
186
188
  if (isRedelivered) {
187
189
  message.ack();
@@ -261,7 +263,7 @@ ActivityExecution.prototype._onExecutionCompleted = function onExecutionComplete
261
263
  this._publishExecutionCompleted('completed', {...postponedMsg.content, ...message.content}, message.properties.correlationId);
262
264
  };
263
265
 
264
- ActivityExecution.prototype._onExecutionDiscarded = function onExecutionDiscarded(message) {
266
+ ActivityExecution.prototype._onExecutionDiscarded = function onExecutionDiscarded(discardType, message) {
265
267
  const postponedMsg = this._ackPostponed(message);
266
268
  const {isRootScope, error} = message.content;
267
269
  if (!isRootScope && !postponedMsg) return;
@@ -284,11 +286,7 @@ ActivityExecution.prototype._onExecutionDiscarded = function onExecutionDiscarde
284
286
  postponed.splice(0);
285
287
  for (const api of subApis) api.discard();
286
288
 
287
- if (error) {
288
- return this._publishExecutionCompleted('error', cloneContent(message.content, {error}), correlationId);
289
- }
290
-
291
- this._publishExecutionCompleted('discard', message.content, correlationId);
289
+ this._publishExecutionCompleted(discardType, cloneContent(message.content), correlationId);
292
290
  };
293
291
 
294
292
  ActivityExecution.prototype._publishExecutionCompleted = function publishExecutionCompleted(completionType, completeContent, correlationId) {
@@ -106,6 +106,12 @@ Object.defineProperty(Definition.prototype, 'stopped', {
106
106
  },
107
107
  });
108
108
 
109
+ Object.defineProperty(Definition.prototype, 'activityStatus', {
110
+ get() {
111
+ return this[kExec].execution && this[kExec].execution.activityStatus || 'idle';
112
+ },
113
+ });
114
+
109
115
  Definition.prototype.run = function run(optionsOrCallback, optionalCallback) {
110
116
  const [runOptions, callback] = getOptionsAndCallback(optionsOrCallback, optionalCallback);
111
117
  if (this.isRunning) {
@@ -182,8 +188,6 @@ Definition.prototype.recover = function recover(state) {
182
188
 
183
189
  Definition.prototype.shake = function shake(startId) {
184
190
  let result = {};
185
- const broker = this.broker;
186
-
187
191
  let bps;
188
192
  if (startId) {
189
193
  const startActivity = this.getActivityById(startId);
@@ -193,30 +197,29 @@ Definition.prototype.shake = function shake(startId) {
193
197
  bps = [bp];
194
198
  } else bps = this.getProcesses();
195
199
 
196
- bps.forEach(shakeProcess);
200
+ bps.forEach((bp) => {
201
+ result = {...result, ...this._shakeProcess(bp, startId)};
202
+ });
197
203
 
198
204
  return result;
205
+ };
199
206
 
200
- function shakeProcess(shakeBp) {
201
- let shovel;
202
- if (!shakeBp.isRunning) {
203
- shovel = shakeBp.broker.createShovel('shaker', {
204
- exchange: 'event',
205
- pattern: '*.shake#',
206
- }, {
207
- broker,
208
- exchange: 'event',
209
- });
210
- }
207
+ Definition.prototype._shakeProcess = function shakeProcess(shakeBp, startId) {
208
+ let shovel;
209
+ if (!shakeBp.isRunning) {
210
+ shovel = shakeBp.broker.createShovel('shaker', {
211
+ exchange: 'event',
212
+ pattern: '*.shake#',
213
+ }, {
214
+ broker: this.broker,
215
+ exchange: 'event',
216
+ });
217
+ }
211
218
 
212
- const shakeResult = shakeBp.shake(startId);
213
- if (shovel) shakeBp.broker.closeShovel('shaker');
219
+ const shakeResult = shakeBp.shake(startId);
220
+ if (shovel) shakeBp.broker.closeShovel('shaker');
214
221
 
215
- result = {
216
- ...result,
217
- ...shakeResult,
218
- };
219
- }
222
+ return shakeResult;
220
223
  };
221
224
 
222
225
  Definition.prototype.getState = function getState() {
@@ -101,6 +101,32 @@ Object.defineProperty(DefinitionExecution.prototype, 'isRunning', {
101
101
  },
102
102
  });
103
103
 
104
+ Object.defineProperty(DefinitionExecution.prototype, 'activityStatus', {
105
+ get() {
106
+ let status = 'idle';
107
+ const running = this[kProcesses].running;
108
+ if (!running || !running.length) return status;
109
+
110
+ for (const bp of running) {
111
+ const bpStatus = bp.activityStatus;
112
+ switch (bp.activityStatus) {
113
+ case 'idle':
114
+ break;
115
+ case 'executing':
116
+ return bpStatus;
117
+ case 'timer':
118
+ status = bpStatus;
119
+ break;
120
+ case 'wait':
121
+ if (status === 'idle') status = bpStatus;
122
+ break;
123
+ }
124
+ }
125
+
126
+ return status;
127
+ },
128
+ });
129
+
104
130
  DefinitionExecution.prototype.execute = function execute(executeMessage) {
105
131
  if (!executeMessage) throw new Error('Definition execution requires message');
106
132
  const content = executeMessage.content;
@@ -1,7 +1,5 @@
1
- import {brokerSafeId} from '../shared.js';
2
1
  import {cloneContent, shiftParent} from '../messageHelper.js';
3
2
 
4
- const kMessageQ = Symbol.for('cancelQ');
5
3
  const kCompleted = Symbol.for('completed');
6
4
  const kExecuteMessage = Symbol.for('executeMessage');
7
5
 
@@ -11,19 +9,12 @@ export default function CancelEventDefinition(activity, eventDefinition) {
11
9
 
12
10
  this.id = id;
13
11
  this.type = type;
14
- const reference = this.reference = {referenceType: 'cancel'};
12
+ this.reference = {referenceType: 'cancel'};
15
13
  this.isThrowing = isThrowing;
16
14
  this.activity = activity;
17
15
  this.environment = environment;
18
16
  this.broker = broker;
19
17
  this.logger = environment.Logger(type.toLowerCase());
20
-
21
- if (!isThrowing) {
22
- this[kCompleted] = false;
23
- const messageQueueName = `${reference.referenceType}-${brokerSafeId(id)}-q`;
24
- this[kMessageQ] = broker.assertQueue(messageQueueName, {autoDelete: false, durable: true});
25
- broker.bindQueue(messageQueueName, 'api', `*.${reference.referenceType}.#`, {durable: true, priority: 400});
26
- }
27
18
  }
28
19
 
29
20
  Object.defineProperty(CancelEventDefinition.prototype, 'executionId', {
@@ -46,88 +37,57 @@ CancelEventDefinition.prototype.executeCatch = function executeCatch(executeMess
46
37
  const parentExecutionId = parent.executionId;
47
38
 
48
39
  const broker = this.broker;
49
- const onCatchMessage = this._onCatchMessage.bind(this);
50
- this[kMessageQ].consume(onCatchMessage, {
51
- noAck: true,
52
- consumerTag: `_oncancel-${executionId}`,
53
- });
54
40
 
55
- if (this[kCompleted]) return;
41
+ this._debug('expect cancel');
56
42
 
57
- const onApiMessage = this._onApiMessage.bind(this);
58
- broker.subscribeTmp('api', `activity.#.${parentExecutionId}`, onApiMessage, {
59
- noAck: true,
60
- consumerTag: `_api-parent-${executionId}`,
61
- });
62
- broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {
43
+ broker.subscribeTmp('api', `activity.#.${parent.executionId}#`, this._onApiMessage.bind(this), {
63
44
  noAck: true,
64
45
  consumerTag: `_api-${executionId}`,
65
46
  });
66
47
 
67
- this._debug('expect cancel');
68
-
69
- const exchangeKey = `execute.canceled.${executionId}`;
70
- broker.subscribeOnce('execution', exchangeKey, onCatchMessage, {
48
+ const expectRoutingKey = `execute.cancelled.${executionId}`;
49
+ broker.subscribeOnce('execution', expectRoutingKey, this._onCatchMessage.bind(this), {
71
50
  consumerTag: `_onattached-cancel-${executionId}`,
72
51
  });
73
52
 
74
53
  broker.publish('execution', 'execute.expect', cloneContent(executeContent, {
75
- pattern: '#.cancel',
54
+ pattern: 'activity.execution.cancel',
76
55
  exchange: 'execution',
77
- exchangeKey,
56
+ expectRoutingKey,
78
57
  }));
58
+
59
+ const waitContent = cloneContent(executeContent, {
60
+ executionId: parentExecutionId,
61
+ condition: this.condition,
62
+ expect: 'cancel',
63
+ });
64
+ waitContent.parent = shiftParent(parent);
65
+
66
+ broker.publish('event', 'activity.wait', waitContent);
79
67
  };
80
68
 
81
69
  CancelEventDefinition.prototype.executeThrow = function executeThrow(executeMessage) {
82
- const {isTransaction} = this.environment.variables.content || {};
83
70
  const executeContent = executeMessage.content;
84
71
  const {executionId, parent} = executeContent;
85
72
 
86
- this.logger.debug(`<${executionId} (${this.activity.id})> throw cancel${isTransaction ? ' transaction' : ''}`);
73
+ this.logger.debug(`<${executionId} (${this.activity.id})> throw cancel`);
87
74
 
88
75
  const broker = this.broker;
89
76
  const cancelContent = cloneContent(executeContent, {
90
- isTransaction,
91
77
  executionId: parent.executionId,
92
78
  state: 'throw',
93
79
  });
94
80
  cancelContent.parent = shiftParent(parent);
95
81
 
96
- broker.publish('event', 'activity.cancel', cancelContent, {type: 'cancel', delegate: isTransaction});
82
+ broker.publish('event', 'activity.cancel', cancelContent, { type: 'cancel' });
97
83
 
98
84
  return broker.publish('execution', 'execute.completed', cloneContent(executeContent));
99
85
  };
100
86
 
101
87
  CancelEventDefinition.prototype._onCatchMessage = function onCatchMessage(_, message) {
102
- if (message.content && message.content.isTransaction) return this._onCancelTransaction(_, message);
103
-
104
- this._debug(`cancel caught from <${message.content.id}>`);
105
- return this._complete(message.content.message);
106
- };
107
-
108
- CancelEventDefinition.prototype._onCancelTransaction = function onCancelTransaction(_, message) {
109
- const broker = this.broker, executionId = this.executionId;
110
- const executeContent = this[kExecuteMessage].content;
111
- broker.cancel(`_oncancel-${executionId}`);
112
-
113
- this._debug(`cancel transaction thrown by <${message.content.id}>`);
114
-
115
- broker.assertExchange('cancel', 'topic');
116
- broker.publish('execution', 'execute.detach', cloneContent(executeContent, {
117
- pattern: '#',
118
- bindExchange: 'cancel',
119
- sourceExchange: 'event',
120
- sourcePattern: '#',
121
- }));
122
-
123
- broker.publish('event', 'activity.compensate', cloneContent(message.content, {
124
- state: 'throw',
125
- }), {type: 'compensate', delegate: true});
126
-
127
- broker.subscribeTmp('cancel', 'activity.leave', (__, {content: msg}) => {
128
- if (msg.id !== executeContent.attachedTo) return;
129
- return this._complete(message.content.message);
130
- }, {noAck: true, consumerTag: `_oncancelend-${executionId}`});
88
+ const content = message.content;
89
+ this._debug(`cancel caught from <${content.id}>`);
90
+ return this._complete(content.message);
131
91
  };
132
92
 
133
93
  CancelEventDefinition.prototype._complete = function complete(output) {
@@ -158,12 +118,8 @@ CancelEventDefinition.prototype._onApiMessage = function onApiMessage(routingKey
158
118
 
159
119
  CancelEventDefinition.prototype._stop = function stop() {
160
120
  const broker = this.broker, executionId = this.executionId;
161
- broker.cancel(`_api-parent-${executionId}`);
162
- broker.cancel(`_api-${executionId}`);
163
- broker.cancel(`_oncancel-${executionId}`);
164
- broker.cancel(`_oncancelend-${executionId}`);
165
121
  broker.cancel(`_onattached-cancel-${executionId}`);
166
- this[kMessageQ].purge();
122
+ broker.cancel(`_api-${executionId}`);
167
123
  };
168
124
 
169
125
  CancelEventDefinition.prototype._debug = function debug(msg) {