bpmn-elements 14.0.1 → 15.0.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 (55) hide show
  1. package/README.md +0 -4
  2. package/dist/Context.js +41 -35
  3. package/dist/Environment.js +1 -1
  4. package/dist/Expressions.js +1 -1
  5. package/dist/MessageFormatter.js +0 -1
  6. package/dist/Timers.js +5 -9
  7. package/dist/Tracker.js +15 -19
  8. package/dist/activity/Activity.js +17 -11
  9. package/dist/activity/ActivityExecution.js +43 -29
  10. package/dist/definition/Definition.js +1 -1
  11. package/dist/definition/DefinitionExecution.js +64 -55
  12. package/dist/eventDefinitions/EscalationEventDefinition.js +1 -1
  13. package/dist/eventDefinitions/LinkEventDefinition.js +1 -1
  14. package/dist/eventDefinitions/MessageEventDefinition.js +1 -1
  15. package/dist/eventDefinitions/SignalEventDefinition.js +3 -2
  16. package/dist/events/BoundaryEvent.js +11 -9
  17. package/dist/events/EndEvent.js +1 -1
  18. package/dist/events/IntermediateCatchEvent.js +1 -1
  19. package/dist/events/IntermediateThrowEvent.js +1 -1
  20. package/dist/events/StartEvent.js +1 -1
  21. package/dist/flows/SequenceFlow.js +1 -1
  22. package/dist/gateways/EventBasedGateway.js +1 -1
  23. package/dist/gateways/ExclusiveGateway.js +1 -1
  24. package/dist/gateways/InclusiveGateway.js +1 -1
  25. package/dist/gateways/ParallelGateway.js +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/io/InputOutputSpecification.js +1 -1
  28. package/dist/io/Properties.js +1 -1
  29. package/dist/process/Process.js +1 -1
  30. package/dist/process/ProcessExecution.js +67 -40
  31. package/dist/tasks/CallActivity.js +1 -1
  32. package/dist/tasks/LoopCharacteristics.js +2 -2
  33. package/dist/tasks/ReceiveTask.js +1 -1
  34. package/dist/tasks/ScriptTask.js +1 -1
  35. package/dist/tasks/ServiceImplementation.js +1 -1
  36. package/dist/tasks/ServiceTask.js +1 -1
  37. package/dist/tasks/SignalTask.js +1 -1
  38. package/dist/tasks/StandardLoopCharacteristics.js +1 -1
  39. package/dist/tasks/SubProcess.js +27 -28
  40. package/dist/tasks/Task.js +1 -1
  41. package/dist/tasks/Transaction.js +1 -1
  42. package/package.json +5 -3
  43. package/src/Context.js +51 -35
  44. package/src/MessageFormatter.js +0 -3
  45. package/src/Timers.js +5 -9
  46. package/src/Tracker.js +13 -17
  47. package/src/activity/Activity.js +5 -3
  48. package/src/activity/ActivityExecution.js +43 -26
  49. package/src/definition/DefinitionExecution.js +64 -54
  50. package/src/eventDefinitions/SignalEventDefinition.js +1 -1
  51. package/src/events/BoundaryEvent.js +10 -8
  52. package/src/process/ProcessExecution.js +70 -40
  53. package/src/tasks/LoopCharacteristics.js +2 -2
  54. package/src/tasks/SubProcess.js +27 -27
  55. package/types/types.d.ts +1 -1
@@ -24,21 +24,21 @@ export default function DefinitionExecution(definition, context) {
24
24
  this.context = context;
25
25
 
26
26
  const processes = context.getProcesses();
27
- const ids = [];
28
- const executable = [];
27
+ const ids = new Set();
28
+ const executable = new Set();
29
29
  for (const bp of processes) {
30
30
  bp.environment.assignVariables(environment.variables);
31
31
  bp.environment.assignSettings(environment.settings);
32
- ids.push(bp.id);
33
- if (bp.isExecutable) executable.push(bp);
32
+ ids.add(bp.id);
33
+ if (bp.isExecutable) executable.add(bp);
34
34
  }
35
35
 
36
36
  this[kProcesses] = {
37
37
  processes,
38
- running: [],
39
38
  ids,
40
39
  executable,
41
- postponed: [],
40
+ running: new Set(),
41
+ postponed: new Set(),
42
42
  };
43
43
 
44
44
  broker.assertExchange('execution', 'topic', { autoDelete: false, durable: true });
@@ -79,12 +79,12 @@ Object.defineProperties(DefinitionExecution.prototype, {
79
79
  },
80
80
  processes: {
81
81
  get() {
82
- return this[kProcesses].running;
82
+ return [...this[kProcesses].running];
83
83
  },
84
84
  },
85
85
  postponedCount: {
86
86
  get() {
87
- return this[kProcesses].postponed.length;
87
+ return this[kProcesses].postponed.size;
88
88
  },
89
89
  },
90
90
  isRunning: {
@@ -96,7 +96,7 @@ Object.defineProperties(DefinitionExecution.prototype, {
96
96
  get() {
97
97
  let status = 'idle';
98
98
  const running = this[kProcesses].running;
99
- if (!running || !running.length) return status;
99
+ if (!running.size) return status;
100
100
 
101
101
  for (const bp of running) {
102
102
  const bpStatus = bp.activityStatus;
@@ -143,13 +143,15 @@ DefinitionExecution.prototype.execute = function execute(executeMessage) {
143
143
  if (content.processId) {
144
144
  const startWithProcess = this.getProcessById(content.processId);
145
145
  if (startWithProcess) {
146
- executable.splice(0);
147
- executable.push(startWithProcess);
146
+ executable.clear();
147
+ executable.add(startWithProcess);
148
148
  }
149
149
  }
150
150
 
151
151
  this._debug('execute definition');
152
- running.push(...executable);
152
+ for (const bp of executable) {
153
+ running.add(bp);
154
+ }
153
155
  this._activate(executable);
154
156
  this._start();
155
157
  return true;
@@ -162,7 +164,7 @@ DefinitionExecution.prototype.resume = function resume() {
162
164
 
163
165
  const { running, postponed } = this[kProcesses];
164
166
  this._activate(running);
165
- postponed.splice(0);
167
+ postponed.clear();
166
168
  this[kProcessesQ].consume(this[kMessageHandlers].onProcessMessage, {
167
169
  prefetch: 1000,
168
170
  consumerTag: `_definition-activity-${this.executionId}`,
@@ -184,22 +186,22 @@ DefinitionExecution.prototype.recover = function recover(state) {
184
186
  this._debug(`recover ${this[kStatus]} definition execution`);
185
187
 
186
188
  const running = this[kProcesses].running;
187
- running.splice(0);
189
+ running.clear();
188
190
 
189
- const ids = [];
191
+ const ids = new Set();
190
192
  for (const bpState of state.processes) {
191
193
  const bpid = bpState.id;
192
194
  let bp;
193
- if (ids.indexOf(bpid) > -1) {
195
+ if (ids.has(bpid)) {
194
196
  bp = this.context.getNewProcessById(bpid);
195
197
  } else {
196
198
  bp = this.getProcessById(bpid);
197
199
  }
198
200
  if (!bp) continue;
199
201
 
200
- ids.push(bpid);
202
+ ids.add(bpid);
201
203
  bp.recover(bpState);
202
- running.push(bp);
204
+ running.add(bp);
203
205
  }
204
206
 
205
207
  return this;
@@ -211,7 +213,7 @@ DefinitionExecution.prototype.stop = function stop() {
211
213
 
212
214
  DefinitionExecution.prototype.getProcesses = function getProcesses() {
213
215
  const { running, processes } = this[kProcesses];
214
- const result = running.slice();
216
+ const result = [...running];
215
217
  for (const bp of processes) {
216
218
  if (!result.find((runningBp) => bp.id === runningBp.id)) result.push(bp);
217
219
  }
@@ -227,26 +229,31 @@ DefinitionExecution.prototype.getProcessesById = function getProcessesById(proce
227
229
  };
228
230
 
229
231
  DefinitionExecution.prototype.getProcessByExecutionId = function getProcessByExecutionId(processExecutionId) {
230
- const running = this[kProcesses].running;
231
- return running.find((bp) => bp.executionId === processExecutionId);
232
+ for (const bp of this[kProcesses].running) {
233
+ if (bp.executionId === processExecutionId) return bp;
234
+ }
232
235
  };
233
236
 
234
237
  DefinitionExecution.prototype.getRunningProcesses = function getRunningProcesses() {
235
- const running = this[kProcesses].running;
236
- return running.filter((bp) => bp.executionId);
238
+ return [...this[kProcesses].running].filter((bp) => bp.executionId);
237
239
  };
238
240
 
239
241
  DefinitionExecution.prototype.getExecutableProcesses = function getExecutableProcesses() {
240
- return this[kProcesses].executable.slice();
242
+ return [...this[kProcesses].executable];
241
243
  };
242
244
 
243
245
  DefinitionExecution.prototype.getState = function getState() {
246
+ const processes = [];
247
+ for (const bp of this[kProcesses].running) {
248
+ processes.push(bp.getState());
249
+ }
250
+
244
251
  return {
245
252
  executionId: this.executionId,
246
253
  stopped: this[kStopped],
247
254
  completed: this[kCompleted],
248
255
  status: this[kStatus],
249
- processes: this[kProcesses].running.map((bp) => bp.getState()),
256
+ processes,
250
257
  };
251
258
  };
252
259
 
@@ -263,31 +270,32 @@ DefinitionExecution.prototype.getApi = function getApi(apiMessage) {
263
270
  const self = this;
264
271
 
265
272
  api.getExecuting = function getExecuting() {
266
- return postponed.reduce((result, msg) => {
273
+ const apis = [];
274
+ for (const msg of postponed) {
267
275
  const bpApi = self._getProcessApi(msg);
268
- if (bpApi) result.push(bpApi);
269
- return result;
270
- }, []);
276
+ if (bpApi) apis.push(bpApi);
277
+ }
278
+ return apis;
271
279
  };
272
280
 
273
281
  return api;
274
282
  };
275
283
 
276
284
  DefinitionExecution.prototype.getPostponed = function getPostponed(...args) {
277
- const running = this[kProcesses].running;
278
- return running.reduce((result, p) => {
279
- result = result.concat(p.getPostponed(...args));
280
- return result;
281
- }, []);
285
+ let result = [];
286
+ for (const bp of this[kProcesses].running) {
287
+ result = result.concat(bp.getPostponed(...args));
288
+ }
289
+ return result;
282
290
  };
283
291
 
284
292
  DefinitionExecution.prototype._start = function start() {
285
293
  const { ids, executable, postponed } = this[kProcesses];
286
- if (!ids.length) {
294
+ if (!ids.size) {
287
295
  return this._complete('completed');
288
296
  }
289
297
 
290
- if (!executable.length) {
298
+ if (!executable.size) {
291
299
  return this._complete('error', { error: new Error('No executable process') });
292
300
  }
293
301
 
@@ -296,7 +304,7 @@ DefinitionExecution.prototype._start = function start() {
296
304
  for (const bp of executable) bp.init();
297
305
  for (const bp of executable) bp.run();
298
306
 
299
- postponed.splice(0);
307
+ postponed.clear();
300
308
  this[kProcessesQ].assertConsumer(this[kMessageHandlers].onProcessMessage, {
301
309
  prefetch: 1000,
302
310
  consumerTag: `_definition-activity-${this.executionId}`,
@@ -348,7 +356,7 @@ DefinitionExecution.prototype._onChildEvent = function onChildEvent(routingKey,
348
356
  const content = message.content;
349
357
  const parent = (content.parent = content.parent || {});
350
358
 
351
- const isDirectChild = this[kProcesses].ids.indexOf(content.id) > -1;
359
+ const isDirectChild = this[kProcesses].ids.has(content.id);
352
360
  if (isDirectChild) {
353
361
  parent.executionId = this.executionId;
354
362
  } else {
@@ -434,7 +442,7 @@ DefinitionExecution.prototype._onProcessMessage = function onProcessMessage(rout
434
442
  { mandatory: true, type: 'error' },
435
443
  );
436
444
  } else {
437
- for (const bp of this[kProcesses].running.slice()) {
445
+ for (const bp of new Set(this[kProcesses].running)) {
438
446
  if (bp.id !== childId) bp.stop();
439
447
  }
440
448
 
@@ -450,13 +458,16 @@ DefinitionExecution.prototype._onProcessMessage = function onProcessMessage(rout
450
458
  DefinitionExecution.prototype._stateChangeMessage = function stateChangeMessage(message, postponeMessage) {
451
459
  let previousMsg;
452
460
  const postponed = this[kProcesses].postponed;
453
- const idx = postponed.findIndex((msg) => msg.content.executionId === message.content.executionId);
454
- if (idx > -1) {
455
- previousMsg = postponed.splice(idx, 1)[0];
461
+ for (const msg of postponed) {
462
+ if (msg.content.executionId === message.content.executionId) {
463
+ previousMsg = msg;
464
+ postponed.delete(msg);
465
+ break;
466
+ }
456
467
  }
457
468
 
458
469
  if (previousMsg) previousMsg.ack();
459
- if (postponeMessage) postponed.push(message);
470
+ if (postponeMessage) postponed.add(message);
460
471
  };
461
472
 
462
473
  DefinitionExecution.prototype._onProcessCompleted = function onProcessCompleted(message) {
@@ -479,9 +490,9 @@ DefinitionExecution.prototype._onProcessCompleted = function onProcessCompleted(
479
490
 
480
491
  DefinitionExecution.prototype._onStopped = function onStopped(message) {
481
492
  const running = this[kProcesses].running;
482
- this._debug(`stop definition execution (stop process executions ${running.length})`);
493
+ this._debug(`stop definition execution (stop process executions ${running.size})`);
483
494
  this[kProcessesQ].close();
484
- for (const bp of running.slice()) bp.stop();
495
+ for (const bp of new Set(running)) bp.stop();
485
496
  this._deactivate();
486
497
 
487
498
  this[kStopped] = true;
@@ -505,7 +516,7 @@ DefinitionExecution.prototype._onApiMessage = function onApiMessage(routingKey,
505
516
  }
506
517
 
507
518
  if (delegate) {
508
- for (const bp of this[kProcesses].running.slice()) {
519
+ for (const bp of new Set(this[kProcesses].running)) {
509
520
  bp.broker.publish('api', routingKey, cloneContent(message.content), message.properties);
510
521
  }
511
522
  }
@@ -528,7 +539,7 @@ DefinitionExecution.prototype._startProcessesByMessage = function startProcesses
528
539
  if (!bp.executionId) {
529
540
  this._debug(`start <${bp.id}> by <${reference.referenceId}> (${reference.referenceType})`);
530
541
  this._activateProcess(bp);
531
- running.push(bp);
542
+ running.add(bp);
532
543
  bp.init();
533
544
  bp.run();
534
545
  if (reference.referenceType === 'message') return;
@@ -539,7 +550,7 @@ DefinitionExecution.prototype._startProcessesByMessage = function startProcesses
539
550
 
540
551
  const targetProcess = this.context.getNewProcessById(bp.id);
541
552
  this._activateProcess(targetProcess);
542
- running.push(targetProcess);
553
+ running.add(targetProcess);
543
554
  targetProcess.init();
544
555
  targetProcess.run();
545
556
  if (reference.referenceType === 'message') return;
@@ -573,7 +584,7 @@ DefinitionExecution.prototype._onMessageOutbound = function onMessageOutbound(ro
573
584
  targetProcess = targetProcess || this.context.getNewProcessById(target.processId);
574
585
 
575
586
  this._activateProcess(targetProcess);
576
- this[kProcesses].running.push(targetProcess);
587
+ this[kProcesses].running.add(targetProcess);
577
588
  targetProcess.init();
578
589
  targetProcess.run();
579
590
  targetProcess.sendMessage(message);
@@ -605,7 +616,7 @@ DefinitionExecution.prototype._onCallActivity = function onCallActivity(routingK
605
616
  this._debug(`call from <${fromParent.id}.${fromId}> to <${calledElement}>`);
606
617
 
607
618
  this._activateProcess(targetProcess);
608
- this[kProcesses].running.push(targetProcess);
619
+ this[kProcesses].running.add(targetProcess);
609
620
  targetProcess.init(bpExecutionId);
610
621
  targetProcess.run({ inbound: [cloneContent(content)] });
611
622
  };
@@ -672,10 +683,9 @@ DefinitionExecution.prototype._onDelegateMessage = function onDelegateMessage(ro
672
683
  };
673
684
 
674
685
  DefinitionExecution.prototype._removeProcessByExecutionId = function removeProcessByExecutionId(processExecutionId) {
675
- const running = this[kProcesses].running;
676
- const idx = running.findIndex((p) => p.executionId === processExecutionId);
677
- if (idx === -1) return;
678
- return running.splice(idx, 1)[0];
686
+ const bp = this.getProcessByExecutionId(processExecutionId);
687
+ if (bp) this[kProcesses].running.delete(bp);
688
+ return bp;
679
689
  };
680
690
 
681
691
  DefinitionExecution.prototype._complete = function complete(completionType, content, options) {
@@ -108,7 +108,7 @@ SignalEventDefinition.prototype.executeThrow = function executeThrow(executeMess
108
108
  throwContent.parent = shiftParent(parent);
109
109
 
110
110
  const broker = this.broker;
111
- broker.publish('event', 'activity.signal', throwContent, { type: 'signal' });
111
+ broker.publish('event', 'activity.signal', throwContent, { type: 'signal', delegate: true });
112
112
 
113
113
  return broker.publish('execution', 'execute.completed', cloneContent(executeContent));
114
114
  };
@@ -22,8 +22,8 @@ export function BoundaryEventBehaviour(activity) {
22
22
  this.broker = activity.broker;
23
23
  this[kExecution] =
24
24
  activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions, 'execute.bound.completed');
25
- this[kShovels] = [];
26
- this[kAttachedTags] = [];
25
+ this[kShovels] = new Set();
26
+ this[kAttachedTags] = new Set();
27
27
  }
28
28
 
29
29
  Object.defineProperties(BoundaryEventBehaviour.prototype, {
@@ -60,7 +60,7 @@ BoundaryEventBehaviour.prototype.execute = function execute(executeMessage) {
60
60
  consumerTag,
61
61
  priority: 300,
62
62
  });
63
- this[kAttachedTags].push(consumerTag);
63
+ this[kAttachedTags].add(consumerTag);
64
64
 
65
65
  broker.subscribeOnce('api', `activity.#.${executionId}`, this._onApiMessage.bind(this), {
66
66
  consumerTag: `_api-${executionId}`,
@@ -118,7 +118,7 @@ BoundaryEventBehaviour.prototype._onCompleted = function onCompleted(_, { conten
118
118
 
119
119
  if (content.isRecovered && !attachedTo.isRunning) {
120
120
  const attachedExecuteTag = `_on-attached-execute-${executionId}`;
121
- this[kAttachedTags].push(attachedExecuteTag);
121
+ this[kAttachedTags].add(attachedExecuteTag);
122
122
  attachedTo.broker.subscribeOnce(
123
123
  'execution',
124
124
  '#',
@@ -146,7 +146,7 @@ BoundaryEventBehaviour.prototype._onExpectMessage = function onExpectMessage(_,
146
146
  const attachedTo = this.attachedTo;
147
147
 
148
148
  const errorConsumerTag = `_bound-error-listener-${executionId}`;
149
- this[kAttachedTags].push(errorConsumerTag);
149
+ this[kAttachedTags].add(errorConsumerTag);
150
150
 
151
151
  attachedTo.broker.subscribeTmp(
152
152
  'event',
@@ -177,7 +177,7 @@ BoundaryEventBehaviour.prototype._onDetachMessage = function onDetachMessage(_,
177
177
  const { executionId: detachId, bindExchange, sourceExchange, sourcePattern } = content;
178
178
 
179
179
  const shovelName = `_detached-${brokerSafeId(id)}_${detachId}`;
180
- this[kShovels].push(shovelName);
180
+ this[kShovels].add(shovelName);
181
181
 
182
182
  const broker = this.broker;
183
183
  attachedTo.broker.createShovel(
@@ -238,8 +238,10 @@ BoundaryEventBehaviour.prototype._stop = function stop(detach) {
238
238
  const attachedTo = this.attachedTo,
239
239
  broker = this.broker,
240
240
  executionId = this.executionId;
241
- for (const tag of this[kAttachedTags].splice(0)) attachedTo.broker.cancel(tag);
242
- for (const shovelName of this[kShovels].splice(0)) attachedTo.broker.closeShovel(shovelName);
241
+ for (const tag of this[kAttachedTags]) attachedTo.broker.cancel(tag);
242
+ this[kAttachedTags].clear();
243
+ for (const shovelName of this[kShovels]) attachedTo.broker.closeShovel(shovelName);
244
+ this[kShovels].clear();
243
245
 
244
246
  broker.cancel('_execution-tag');
245
247
  broker.cancel(`_execution-completed-${executionId}`);
@@ -29,15 +29,15 @@ function ProcessExecution(parentActivity, context) {
29
29
  this.context = context;
30
30
 
31
31
  this[kElements] = {
32
+ postponed: new Set(),
32
33
  children: context.getActivities(id),
33
34
  associations: context.getAssociations(id),
34
35
  flows: context.getSequenceFlows(id),
35
36
  outboundMessageFlows: context.getMessageFlows(id),
36
37
  startActivities: [],
37
38
  triggeredByEvent: [],
38
- detachedActivities: [],
39
+ detachedActivities: new Set(),
39
40
  startSequences: {},
40
- postponed: [],
41
41
  };
42
42
 
43
43
  const exchangeName = (this._exchangeName = isSubProcess ? 'subprocess-execution' : 'execution');
@@ -76,7 +76,7 @@ Object.defineProperties(ProcessExecution.prototype, {
76
76
  },
77
77
  postponedCount: {
78
78
  get() {
79
- return this[kElements].postponed.length;
79
+ return this[kElements].postponed.size;
80
80
  },
81
81
  },
82
82
  isRunning: {
@@ -130,8 +130,8 @@ ProcessExecution.prototype.resume = function resume() {
130
130
  for (const a of startActivities) a.shake();
131
131
  }
132
132
 
133
- postponed.splice(0);
134
- detachedActivities.splice(0);
133
+ postponed.clear();
134
+ detachedActivities.clear();
135
135
 
136
136
  this[kActivityQ].consume(this[kMessageHandlers].onChildMessage, {
137
137
  prefetch: 1000,
@@ -144,7 +144,7 @@ ProcessExecution.prototype.resume = function resume() {
144
144
  if (status === 'init') return this._start();
145
145
 
146
146
  const tracker = this[kTracker];
147
- for (const msg of postponed.slice()) {
147
+ for (const msg of new Set(postponed)) {
148
148
  const activity = this.getActivityById(msg.content.id);
149
149
  if (!activity) continue;
150
150
  if (msg.content.placeholder) continue;
@@ -160,7 +160,7 @@ ProcessExecution.prototype.resume = function resume() {
160
160
 
161
161
  if (this[kCompleted]) return;
162
162
 
163
- if (!postponed.length && status === 'executing') return this._complete('completed');
163
+ if (!postponed.size && status === 'executing') return this._complete('completed');
164
164
  };
165
165
 
166
166
  ProcessExecution.prototype.getState = function getState() {
@@ -283,7 +283,7 @@ ProcessExecution.prototype.stop = function stop() {
283
283
 
284
284
  ProcessExecution.prototype.getPostponed = function getPostponed(filterFn) {
285
285
  const result = [];
286
- for (const msg of this[kElements].postponed.slice()) {
286
+ for (const msg of this[kElements].postponed) {
287
287
  const api = this._getChildApi(msg);
288
288
  if (!api) continue;
289
289
  if (filterFn && !filterFn(api)) continue;
@@ -347,11 +347,12 @@ ProcessExecution.prototype.getApi = function getApi(message) {
347
347
  const self = this;
348
348
 
349
349
  api.getExecuting = function getExecuting() {
350
- return postponed.reduce((result, msg) => {
350
+ const result = [];
351
+ for (const msg of postponed) {
351
352
  const childApi = self._getChildApi(msg);
352
353
  if (childApi) result.push(childApi);
353
- return result;
354
- }, []);
354
+ }
355
+ return result;
355
356
  };
356
357
 
357
358
  return api;
@@ -377,8 +378,8 @@ ProcessExecution.prototype._start = function start() {
377
378
  this[kStatus] = 'executing';
378
379
  for (const a of startActivities) a.run();
379
380
 
380
- postponed.splice(0);
381
- detachedActivities.splice(0);
381
+ postponed.clear();
382
+ detachedActivities.clear();
382
383
  this[kActivityQ].assertConsumer(this[kMessageHandlers].onChildMessage, {
383
384
  prefetch: 1000,
384
385
  consumerTag: `_process-activity-${this.executionId}`,
@@ -565,9 +566,13 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
565
566
  message.ack();
566
567
  return this._onCancel(message);
567
568
  case 'activity.error.caught': {
568
- const prevMsg = this[kElements].postponed.find((msg) => {
569
- return msg.content.executionId === content.executionId;
570
- });
569
+ let prevMsg;
570
+ for (const msg of this[kElements].postponed) {
571
+ if (msg.content.executionId === content.executionId) {
572
+ prevMsg = msg;
573
+ break;
574
+ }
575
+ }
571
576
  if (!prevMsg) return message.ack();
572
577
  break;
573
578
  }
@@ -580,7 +585,7 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
580
585
 
581
586
  switch (routingKey) {
582
587
  case 'activity.detach': {
583
- this[kElements].detachedActivities.push(cloneMessage(message));
588
+ this[kElements].detachedActivities.add(cloneMessage(message));
584
589
  break;
585
590
  }
586
591
  case 'activity.cancel': {
@@ -600,10 +605,13 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
600
605
  break;
601
606
  }
602
607
  case 'activity.error': {
603
- const eventCaughtBy = this[kElements].postponed.find((msg) => {
604
- if (msg.fields.routingKey !== 'activity.catch') return;
605
- return msg.content.source && msg.content.source.executionId === content.executionId;
606
- });
608
+ let eventCaughtBy;
609
+ for (const msg of this[kElements].postponed) {
610
+ if (msg.fields.routingKey === 'activity.catch' && msg.content.source && msg.content.source.executionId === content.executionId) {
611
+ eventCaughtBy = msg;
612
+ break;
613
+ }
614
+ }
607
615
  if (eventCaughtBy) {
608
616
  this[kActivityQ].queueMessage({ routingKey: 'activity.error.caught' }, cloneContent(content), {
609
617
  persistent: true,
@@ -619,24 +627,38 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
619
627
  ProcessExecution.prototype._stateChangeMessage = function stateChangeMessage(message, postponeMessage) {
620
628
  const previousMsg = this._popPostponed(message.content);
621
629
  if (previousMsg) previousMsg.ack();
622
- if (postponeMessage) this[kElements].postponed.push(message);
630
+ if (postponeMessage) this[kElements].postponed.add(message);
623
631
  };
624
632
 
625
633
  ProcessExecution.prototype._popPostponed = function popPostponed(byContent) {
626
634
  const { postponed, detachedActivities } = this[kElements];
627
635
 
628
- const postponedIdx = postponed.findIndex((msg) => {
629
- if (msg.content.isSequenceFlow || msg.content.isAssociation) return msg.content.sequenceId === byContent.sequenceId;
630
- return msg.content.executionId === byContent.executionId;
631
- });
632
-
633
636
  let postponedMsg;
634
- if (postponedIdx > -1) {
635
- postponedMsg = postponed.splice(postponedIdx, 1)[0];
637
+ if (byContent.sequenceId) {
638
+ for (const msg of postponed) {
639
+ if (!msg.content.isSequenceFlow && !msg.content.isAssociation) continue;
640
+ if (msg.content.sequenceId === byContent.sequenceId) {
641
+ postponedMsg = msg;
642
+ break;
643
+ }
644
+ }
645
+ } else {
646
+ for (const msg of postponed) {
647
+ if (msg.content.executionId === byContent.executionId) {
648
+ postponedMsg = msg;
649
+ break;
650
+ }
651
+ }
636
652
  }
637
653
 
638
- const detachedIdx = detachedActivities.findIndex((msg) => msg.content.executionId === byContent.executionId);
639
- if (detachedIdx > -1) detachedActivities.splice(detachedIdx, 1);
654
+ if (postponedMsg) postponed.delete(postponedMsg);
655
+
656
+ for (const msg of detachedActivities) {
657
+ if (msg.content.executionId === byContent.executionId) {
658
+ detachedActivities.delete(msg);
659
+ break;
660
+ }
661
+ }
640
662
 
641
663
  return postponedMsg;
642
664
  };
@@ -648,7 +670,7 @@ ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message
648
670
  const { id, type, isEnd } = message.content;
649
671
 
650
672
  const { postponed, detachedActivities, startActivities } = this[kElements];
651
- const postponedCount = postponed.length;
673
+ const postponedCount = postponed.size;
652
674
 
653
675
  if (!postponedCount) {
654
676
  this._debug(`left <${id}> (${type}), pending runs ${postponedCount}`);
@@ -657,9 +679,9 @@ ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message
657
679
  }
658
680
 
659
681
  message.ack();
660
- this._debug(`left <${id}> (${type}), pending runs ${postponedCount}, ${postponed.map((a) => a.content.id).join(',')}`);
682
+ this._debug(`left <${id}> (${type}), pending activities ${postponedCount}`);
661
683
 
662
- if (postponedCount && postponedCount === detachedActivities.length) {
684
+ if (postponedCount && postponedCount === detachedActivities.size) {
663
685
  return this[kActivityQ].queueMessage(
664
686
  { routingKey: 'execution.discard.detached' },
665
687
  {
@@ -706,8 +728,11 @@ ProcessExecution.prototype._stopExecution = function stopExecution(message) {
706
728
 
707
729
  ProcessExecution.prototype._onDiscard = function onDiscard() {
708
730
  this._deactivate();
709
- const running = this[kElements].postponed.splice(0);
710
- this._debug(`discard process execution (discard child executions ${running.length})`);
731
+ const postponed = this[kElements].postponed;
732
+ const running = new Set(postponed);
733
+ postponed.clear();
734
+
735
+ this._debug(`discard process execution (discard child executions ${running.size})`);
711
736
 
712
737
  if (this.isSubProcess) {
713
738
  this.stop();
@@ -722,11 +747,13 @@ ProcessExecution.prototype._onDiscard = function onDiscard() {
722
747
  };
723
748
 
724
749
  ProcessExecution.prototype._onCancel = function onCancel() {
725
- const running = this[kElements].postponed.slice(0);
750
+ const postponed = this[kElements].postponed;
751
+ const running = new Set(postponed);
752
+
726
753
  const isTransaction = this.isTransaction;
727
754
 
728
755
  if (isTransaction) {
729
- this._debug(`cancel transaction execution (cancel child executions ${running.length})`);
756
+ this._debug(`cancel transaction execution (cancel child executions ${running.size})`);
730
757
  this[kStatus] = 'cancel';
731
758
  this.broker.publish(
732
759
  'event',
@@ -744,7 +771,7 @@ ProcessExecution.prototype._onCancel = function onCancel() {
744
771
  }
745
772
  }
746
773
  } else {
747
- this._debug(`cancel process execution (cancel child executions ${running.length})`);
774
+ this._debug(`cancel process execution (cancel child executions ${running.size})`);
748
775
  for (const msg of running) {
749
776
  this._getChildApi(msg).discard();
750
777
  }
@@ -839,7 +866,10 @@ ProcessExecution.prototype._terminate = function terminate(message) {
839
866
  this[kStatus] = 'terminated';
840
867
  this._debug('terminating process execution');
841
868
 
842
- const running = this[kElements].postponed.splice(0);
869
+ const postponed = this[kElements].postponed;
870
+ const running = new Set(postponed);
871
+ postponed.clear();
872
+
843
873
  for (const flow of this.getSequenceFlows()) flow.stop();
844
874
  for (const flow of this.getAssociations()) flow.stop();
845
875
 
@@ -146,12 +146,12 @@ ParallelLoopCharacteristics.prototype.execute = function execute(executeMessage)
146
146
  ParallelLoopCharacteristics.prototype._startBatch = function startBatch() {
147
147
  const chr = this.characteristics;
148
148
  const cardinality = chr.cardinality;
149
- const batch = [];
149
+ const batch = new Set();
150
150
 
151
151
  let startContent = chr.next(this.index);
152
152
  do {
153
153
  chr.debug(`start parallel iteration index ${this.index}`);
154
- batch.push(startContent);
154
+ batch.add(startContent);
155
155
  this.running++;
156
156
  this.index++;
157
157