bpmn-elements 6.0.0 → 8.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 (116) hide show
  1. package/CHANGELOG.md +335 -0
  2. package/README.md +3 -0
  3. package/dist/index.js +52 -44
  4. package/dist/src/Api.js +77 -76
  5. package/dist/src/Context.js +176 -172
  6. package/dist/src/Environment.js +110 -102
  7. package/dist/src/EventBroker.js +89 -88
  8. package/dist/src/ExtensionsMapper.js +2 -2
  9. package/dist/src/MessageFormatter.js +164 -95
  10. package/dist/src/Scripts.js +6 -2
  11. package/dist/src/activity/Activity.js +1106 -916
  12. package/dist/src/activity/ActivityExecution.js +342 -297
  13. package/dist/src/activity/Dummy.js +3 -3
  14. package/dist/src/definition/Definition.js +498 -444
  15. package/dist/src/definition/DefinitionExecution.js +710 -408
  16. package/dist/src/error/Errors.js +17 -7
  17. package/dist/src/eventDefinitions/CancelEventDefinition.js +190 -150
  18. package/dist/src/eventDefinitions/CompensateEventDefinition.js +194 -161
  19. package/dist/src/eventDefinitions/ConditionalEventDefinition.js +197 -135
  20. package/dist/src/eventDefinitions/ErrorEventDefinition.js +207 -165
  21. package/dist/src/eventDefinitions/EscalationEventDefinition.js +175 -141
  22. package/dist/src/eventDefinitions/EventDefinitionExecution.js +157 -129
  23. package/dist/src/eventDefinitions/LinkEventDefinition.js +174 -149
  24. package/dist/src/eventDefinitions/MessageEventDefinition.js +213 -176
  25. package/dist/src/eventDefinitions/SignalEventDefinition.js +203 -161
  26. package/dist/src/eventDefinitions/TerminateEventDefinition.js +21 -23
  27. package/dist/src/eventDefinitions/TimerEventDefinition.js +243 -228
  28. package/dist/src/events/BoundaryEvent.js +180 -144
  29. package/dist/src/events/EndEvent.js +18 -23
  30. package/dist/src/events/IntermediateCatchEvent.js +44 -58
  31. package/dist/src/events/IntermediateThrowEvent.js +18 -23
  32. package/dist/src/events/StartEvent.js +109 -94
  33. package/dist/src/flows/Association.js +94 -100
  34. package/dist/src/flows/MessageFlow.js +86 -103
  35. package/dist/src/flows/SequenceFlow.js +173 -182
  36. package/dist/src/gateways/EventBasedGateway.js +88 -84
  37. package/dist/src/gateways/ExclusiveGateway.js +13 -16
  38. package/dist/src/gateways/InclusiveGateway.js +11 -14
  39. package/dist/src/gateways/ParallelGateway.js +11 -14
  40. package/dist/src/getPropertyValue.js +34 -34
  41. package/dist/src/io/BpmnIO.js +17 -14
  42. package/dist/src/io/EnvironmentDataObject.js +33 -29
  43. package/dist/src/io/EnvironmentDataStore.js +33 -29
  44. package/dist/src/io/EnvironmentDataStoreReference.js +35 -31
  45. package/dist/src/io/InputOutputSpecification.js +177 -168
  46. package/dist/src/io/Properties.js +117 -124
  47. package/dist/src/messageHelper.js +1 -1
  48. package/dist/src/process/Process.js +439 -362
  49. package/dist/src/process/ProcessExecution.js +748 -646
  50. package/dist/src/shared.js +2 -2
  51. package/dist/src/tasks/CallActivity.js +160 -0
  52. package/dist/src/tasks/LoopCharacteristics.js +309 -330
  53. package/dist/src/tasks/ReceiveTask.js +233 -182
  54. package/dist/src/tasks/ScriptTask.js +35 -41
  55. package/dist/src/tasks/ServiceImplementation.js +13 -20
  56. package/dist/src/tasks/ServiceTask.js +82 -75
  57. package/dist/src/tasks/SignalTask.js +97 -93
  58. package/dist/src/tasks/StandardLoopCharacteristics.js +1 -1
  59. package/dist/src/tasks/SubProcess.js +193 -175
  60. package/dist/src/tasks/Task.js +17 -19
  61. package/index.js +2 -0
  62. package/package.json +15 -15
  63. package/src/Api.js +65 -59
  64. package/src/Context.js +145 -140
  65. package/src/Environment.js +116 -100
  66. package/src/EventBroker.js +67 -68
  67. package/src/ExtensionsMapper.js +2 -2
  68. package/src/MessageFormatter.js +132 -74
  69. package/src/activity/Activity.js +915 -775
  70. package/src/activity/ActivityExecution.js +293 -247
  71. package/src/activity/Dummy.js +2 -2
  72. package/src/definition/Definition.js +437 -401
  73. package/src/definition/DefinitionExecution.js +598 -340
  74. package/src/error/Errors.js +11 -6
  75. package/src/eventDefinitions/CancelEventDefinition.js +164 -121
  76. package/src/eventDefinitions/CompensateEventDefinition.js +159 -124
  77. package/src/eventDefinitions/ConditionalEventDefinition.js +147 -104
  78. package/src/eventDefinitions/ErrorEventDefinition.js +190 -131
  79. package/src/eventDefinitions/EscalationEventDefinition.js +139 -101
  80. package/src/eventDefinitions/EventDefinitionExecution.js +127 -95
  81. package/src/eventDefinitions/LinkEventDefinition.js +160 -129
  82. package/src/eventDefinitions/MessageEventDefinition.js +178 -121
  83. package/src/eventDefinitions/SignalEventDefinition.js +162 -106
  84. package/src/eventDefinitions/TerminateEventDefinition.js +19 -19
  85. package/src/eventDefinitions/TimerEventDefinition.js +202 -167
  86. package/src/events/BoundaryEvent.js +156 -115
  87. package/src/events/EndEvent.js +15 -18
  88. package/src/events/IntermediateCatchEvent.js +40 -44
  89. package/src/events/IntermediateThrowEvent.js +15 -18
  90. package/src/events/StartEvent.js +84 -50
  91. package/src/flows/Association.js +98 -112
  92. package/src/flows/MessageFlow.js +81 -97
  93. package/src/flows/SequenceFlow.js +146 -160
  94. package/src/gateways/EventBasedGateway.js +75 -68
  95. package/src/gateways/ExclusiveGateway.js +8 -13
  96. package/src/gateways/InclusiveGateway.js +8 -13
  97. package/src/gateways/ParallelGateway.js +8 -13
  98. package/src/getPropertyValue.js +34 -33
  99. package/src/io/BpmnIO.js +20 -15
  100. package/src/io/EnvironmentDataObject.js +29 -18
  101. package/src/io/EnvironmentDataStore.js +29 -18
  102. package/src/io/EnvironmentDataStoreReference.js +31 -20
  103. package/src/io/InputOutputSpecification.js +154 -157
  104. package/src/io/Properties.js +95 -97
  105. package/src/process/Process.js +378 -333
  106. package/src/process/ProcessExecution.js +603 -553
  107. package/src/tasks/CallActivity.js +130 -0
  108. package/src/tasks/LoopCharacteristics.js +290 -289
  109. package/src/tasks/ReceiveTask.js +174 -107
  110. package/src/tasks/ScriptTask.js +27 -30
  111. package/src/tasks/ServiceImplementation.js +13 -18
  112. package/src/tasks/ServiceTask.js +67 -60
  113. package/src/tasks/SignalTask.js +77 -52
  114. package/src/tasks/StandardLoopCharacteristics.js +1 -1
  115. package/src/tasks/SubProcess.js +184 -157
  116. package/src/tasks/Task.js +15 -19
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = ProcessExecution;
6
+ exports.default = void 0;
7
7
 
8
8
  var _Api = require("../Api");
9
9
 
@@ -11,782 +11,884 @@ var _messageHelper = require("../messageHelper");
11
11
 
12
12
  var _shared = require("../shared");
13
13
 
14
+ var _default = ProcessExecution;
15
+ exports.default = _default;
16
+ const kActivated = Symbol.for('activated');
17
+ const kActivityQ = Symbol.for('activityQ');
18
+ const kCompleted = Symbol.for('completed');
19
+ const kElements = Symbol.for('elements');
20
+ const kExecuteMessage = Symbol.for('executeMessage');
21
+ const kMessageHandlers = Symbol.for('messageHandlers');
22
+ const kParent = Symbol.for('parent');
23
+ const kStatus = Symbol.for('status');
24
+ const kStopped = Symbol.for('stopped');
25
+
14
26
  function ProcessExecution(parentActivity, context) {
15
27
  const {
16
28
  id,
17
29
  type,
18
30
  broker,
19
- logger,
20
31
  isSubProcess
21
32
  } = parentActivity;
22
- const {
23
- environment
24
- } = context;
25
- const children = context.getActivities(id);
26
- const flows = context.getSequenceFlows(id);
27
- const associations = context.getAssociations(id);
28
- const outboundMessageFlows = context.getMessageFlows(id);
29
- const startActivities = [];
30
- const triggeredByEventActivities = [];
31
- const detachedActivities = [];
32
- const postponed = [];
33
- const startSequences = {};
34
- const exchangeName = isSubProcess ? 'subprocess-execution' : 'execution';
33
+ this[kParent] = parentActivity;
34
+ this.id = id;
35
+ this.type = type;
36
+ this.isSubProcess = isSubProcess;
37
+ this.broker = broker;
38
+ this.environment = context.environment;
39
+ this.context = context;
40
+ this[kElements] = {
41
+ children: context.getActivities(id),
42
+ associations: context.getAssociations(id),
43
+ flows: context.getSequenceFlows(id),
44
+ outboundMessageFlows: context.getMessageFlows(id),
45
+ startActivities: [],
46
+ triggeredByEvent: [],
47
+ detachedActivities: [],
48
+ startSequences: {},
49
+ postponed: []
50
+ };
51
+ const exchangeName = this._exchangeName = isSubProcess ? 'subprocess-execution' : 'execution';
35
52
  broker.assertExchange(exchangeName, 'topic', {
36
53
  autoDelete: false,
37
54
  durable: true
38
55
  });
39
- let activityQ,
40
- status = 'init',
41
- executionId,
42
- stopped,
43
- activated,
44
- stateMessage,
45
- completed = false,
46
- executionName;
47
- const processExecution = {
48
- id,
49
- type,
50
- broker,
56
+ this[kCompleted] = false;
57
+ this[kStopped] = false;
58
+ this[kActivated] = false;
59
+ this[kStatus] = 'init';
60
+ this.executionId = undefined;
61
+ this[kMessageHandlers] = {
62
+ onActivityEvent: this._onActivityEvent.bind(this),
63
+ onApiMessage: this._onApiMessage.bind(this),
64
+ onChildMessage: this._onChildMessage.bind(this),
65
+ onMessageFlowEvent: this._onMessageFlowEvent.bind(this)
66
+ };
67
+ }
51
68
 
52
- get environment() {
53
- return environment;
54
- },
69
+ const proto = ProcessExecution.prototype;
70
+ Object.defineProperty(proto, 'stopped', {
71
+ enumerable: true,
55
72
 
56
- get executionId() {
57
- return executionId;
58
- },
73
+ get() {
74
+ return this[kStopped];
75
+ }
59
76
 
60
- get completed() {
61
- return completed;
62
- },
77
+ });
78
+ Object.defineProperty(proto, 'completed', {
79
+ enumerable: true,
63
80
 
64
- get status() {
65
- return status;
66
- },
81
+ get() {
82
+ return this[kCompleted];
83
+ }
67
84
 
68
- get stopped() {
69
- return stopped;
70
- },
85
+ });
86
+ Object.defineProperty(proto, 'status', {
87
+ enumerable: true,
71
88
 
72
- get postponedCount() {
73
- return postponed.length;
74
- },
89
+ get() {
90
+ return this[kStatus];
91
+ }
75
92
 
76
- get isRunning() {
77
- if (activated) return true;
78
- return false;
79
- },
93
+ });
94
+ Object.defineProperty(proto, 'postponedCount', {
95
+ get() {
96
+ return this[kElements].postponed.length;
97
+ }
80
98
 
81
- discard,
82
- execute,
83
- getApi,
84
- getActivityById,
85
- getActivities,
86
- getPostponed,
87
- getSequenceFlows,
88
- getState,
89
- recover,
90
- shake,
91
- stop
92
- };
93
- return processExecution;
94
-
95
- function execute(executeMessage) {
96
- if (!executeMessage) throw new Error('Process execution requires message');
97
- if (!executeMessage.content || !executeMessage.content.executionId) throw new Error('Process execution requires execution id');
98
- const isRedelivered = executeMessage.fields.redelivered;
99
- executionId = executeMessage.content.executionId;
100
- prepare();
101
- stateMessage = (0, _messageHelper.cloneMessage)(executeMessage);
102
- stateMessage.content = { ...stateMessage.content,
103
- executionId,
104
- state: 'start'
105
- };
106
- stopped = false;
107
- environment.assignVariables(executeMessage);
108
- activityQ = broker.assertQueue(`execute-${executionId}-q`, {
109
- durable: true,
110
- autoDelete: false
111
- });
99
+ });
100
+ Object.defineProperty(proto, 'isRunning', {
101
+ get() {
102
+ return this[kActivated];
103
+ }
112
104
 
113
- if (isRedelivered) {
114
- return resume();
115
- }
105
+ });
116
106
 
117
- logger.debug(`<${executionName}> execute`, isSubProcess ? 'sub process' : 'process');
118
- activate();
119
- start();
120
- return true;
107
+ proto.execute = function execute(executeMessage) {
108
+ if (!executeMessage) throw new Error('Process execution requires message');
109
+ if (!executeMessage.content || !executeMessage.content.executionId) throw new Error('Process execution requires execution id');
110
+ const executionId = this.executionId = executeMessage.content.executionId;
111
+ this[kExecuteMessage] = (0, _messageHelper.cloneMessage)(executeMessage, {
112
+ executionId,
113
+ state: 'start'
114
+ });
115
+ this[kStopped] = false;
116
+ this.environment.assignVariables(executeMessage);
117
+ this[kActivityQ] = this.broker.assertQueue(`execute-${executionId}-q`, {
118
+ durable: true,
119
+ autoDelete: false
120
+ });
121
+
122
+ if (executeMessage.fields.redelivered) {
123
+ return this.resume();
121
124
  }
122
125
 
123
- function resume() {
124
- logger.debug(`<${executionName}> resume process execution at`, status);
125
- if (completed) return complete('completed');
126
- activate();
126
+ this._debug(`execute ${this.isSubProcess ? 'sub process' : 'process'}`);
127
127
 
128
- if (startActivities.length > 1) {
129
- startActivities.forEach(a => a.shake());
130
- }
128
+ this._activate();
131
129
 
132
- postponed.splice(0);
133
- detachedActivities.splice(0);
134
- activityQ.consume(onChildMessage, {
135
- prefetch: 1000,
136
- consumerTag: `_process-activity-${executionId}`
137
- });
138
- if (completed) return complete('completed');
130
+ this._start();
139
131
 
140
- switch (status) {
141
- case 'init':
142
- return start();
132
+ return true;
133
+ };
143
134
 
144
- case 'executing':
145
- {
146
- if (!postponed.length) return complete('completed');
147
- break;
148
- }
149
- }
135
+ proto.resume = function resume() {
136
+ this._debug(`resume process execution at ${this.status}`);
150
137
 
151
- postponed.slice().forEach(({
152
- content
153
- }) => {
154
- const activity = getActivityById(content.id);
155
- if (!activity) return;
156
- if (content.placeholder) return;
157
- activity.resume();
158
- });
138
+ if (this[kCompleted]) return this._complete('completed');
139
+
140
+ this._activate();
141
+
142
+ const {
143
+ startActivities,
144
+ detachedActivities,
145
+ postponed
146
+ } = this[kElements];
147
+
148
+ if (startActivities.length > 1) {
149
+ for (const a of startActivities) a.shake();
159
150
  }
160
151
 
161
- function start() {
162
- if (children.length === 0) {
163
- return complete('completed');
164
- }
152
+ postponed.splice(0);
153
+ detachedActivities.splice(0);
154
+ this[kActivityQ].consume(this[kMessageHandlers].onChildMessage, {
155
+ prefetch: 1000,
156
+ consumerTag: `_process-activity-${this.executionId}`
157
+ });
158
+ if (this[kCompleted]) return;
165
159
 
166
- status = 'start';
167
- const executeContent = { ...stateMessage.content,
168
- state: status
169
- };
170
- broker.publish(exchangeName, 'execute.start', (0, _messageHelper.cloneContent)(executeContent));
160
+ switch (this.status) {
161
+ case 'init':
162
+ return this._start();
171
163
 
172
- if (startActivities.length > 1) {
173
- startActivities.forEach(a => a.shake());
174
- }
164
+ case 'executing':
165
+ {
166
+ if (!postponed.length) return this._complete('completed');
167
+ break;
168
+ }
169
+ }
175
170
 
176
- startActivities.forEach(activity => activity.init());
177
- startActivities.forEach(activity => activity.run());
178
- postponed.splice(0);
179
- detachedActivities.splice(0);
180
- activityQ.assertConsumer(onChildMessage, {
181
- prefetch: 1000,
182
- consumerTag: `_process-activity-${executionId}`
183
- });
171
+ for (const {
172
+ content
173
+ } of postponed.slice()) {
174
+ const activity = this.getActivityById(content.id);
175
+ if (!activity) continue;
176
+ if (content.placeholder) continue;
177
+ activity.resume();
184
178
  }
179
+ };
185
180
 
186
- function recover(state) {
187
- if (!state) return processExecution;
188
- executionId = state.executionId;
189
- prepare();
190
- stopped = state.stopped;
191
- completed = state.completed;
192
- status = state.status;
193
- logger.debug(`<${executionName}> recover process execution at`, status);
194
-
195
- if (state.messageFlows) {
196
- state.messageFlows.forEach(flowState => {
197
- const flow = getMessageFlowById(flowState.id);
198
- if (!flow) return;
199
- flow.recover(flowState);
200
- });
181
+ proto.recover = function recover(state) {
182
+ if (!state) return this;
183
+ this.executionId = state.executionId;
184
+ this[kStopped] = state.stopped;
185
+ this[kCompleted] = state.completed;
186
+ this[kStatus] = state.status;
187
+
188
+ this._debug(`recover process execution at ${this.status}`);
189
+
190
+ if (state.messageFlows) {
191
+ for (const flowState of state.messageFlows) {
192
+ const flow = this._getMessageFlowById(flowState.id);
193
+
194
+ if (!flow) continue;
195
+ flow.recover(flowState);
201
196
  }
197
+ }
202
198
 
203
- if (state.associations) {
204
- state.associations.forEach(associationState => {
205
- const association = getAssociationById(associationState.id);
206
- if (!association) return;
207
- association.recover(associationState);
208
- });
199
+ if (state.associations) {
200
+ for (const associationState of state.associations) {
201
+ const association = this._getAssociationById(associationState.id);
202
+
203
+ if (!association) continue;
204
+ association.recover(associationState);
209
205
  }
206
+ }
210
207
 
211
- if (state.flows) {
212
- state.flows.forEach(flowState => {
213
- const flow = getFlowById(flowState.id);
214
- if (!flow) return;
215
- flow.recover(flowState);
216
- });
208
+ if (state.flows) {
209
+ for (const flowState of state.flows) {
210
+ const flow = this._getFlowById(flowState.id);
211
+
212
+ if (!flow) continue;
213
+ flow.recover(flowState);
217
214
  }
215
+ }
218
216
 
219
- if (state.children) {
220
- state.children.forEach(childState => {
221
- const child = getActivityById(childState.id);
222
- if (!child) return;
223
- child.recover(childState);
224
- });
217
+ if (state.children) {
218
+ for (const childState of state.children) {
219
+ const child = this.getActivityById(childState.id);
220
+ if (!child) continue;
221
+ child.recover(childState);
225
222
  }
223
+ }
226
224
 
227
- return processExecution;
225
+ return this;
226
+ };
227
+
228
+ proto.shake = function shake(fromId) {
229
+ let executing = true;
230
+ const id = this.id;
231
+
232
+ if (!this.isRunning) {
233
+ executing = false;
234
+ this.executionId = (0, _shared.getUniqueId)(id);
235
+
236
+ this._activate();
228
237
  }
229
238
 
230
- function shake(fromId) {
231
- let executing = true;
239
+ const toShake = fromId ? [this.getActivityById(fromId)].filter(Boolean) : this[kElements].startActivities;
240
+ const result = {};
241
+ this.broker.subscribeTmp('event', '*.shake.*', (routingKey, {
242
+ content
243
+ }) => {
244
+ let isLooped = false;
245
+
246
+ switch (routingKey) {
247
+ case 'flow.shake.loop':
248
+ isLooped = true;
232
249
 
233
- if (!processExecution.isRunning) {
234
- executing = false;
235
- executionId = (0, _shared.getUniqueId)(id);
236
- prepare();
237
- activate();
250
+ case 'activity.shake.end':
251
+ {
252
+ const {
253
+ id: shakeId,
254
+ parent: shakeParent
255
+ } = content;
256
+ if (shakeParent.id !== id) return;
257
+ result[shakeId] = result[shakeId] || [];
258
+ result[shakeId].push({ ...content,
259
+ isLooped
260
+ });
261
+ break;
262
+ }
238
263
  }
264
+ }, {
265
+ noAck: true,
266
+ consumerTag: `_shaker-${this.executionId}`
267
+ });
239
268
 
240
- const toShake = fromId ? [getActivityById(fromId)].filter(Boolean) : startActivities;
241
- const result = {};
242
- broker.subscribeTmp('event', '*.shake.*', (routingKey, {
243
- content
244
- }) => {
245
- let isLooped = false;
269
+ for (const a of toShake) a.shake();
246
270
 
247
- switch (routingKey) {
248
- case 'flow.shake.loop':
249
- isLooped = true;
271
+ if (!executing) this._deactivate();
272
+ this.broker.cancel(`_shaker-${this.executionId}`);
273
+ return result;
274
+ };
250
275
 
251
- case 'activity.shake.end':
252
- onShakeEnd(content, isLooped);
253
- break;
254
- }
255
- }, {
256
- noAck: true,
257
- consumerTag: `_shaker-${executionId}`
258
- });
259
- toShake.forEach(a => a.shake());
260
- if (!executing) deactivate();
261
- broker.cancel(`_shaker-${executionId}`);
262
- return result;
276
+ proto.stop = function stop() {
277
+ this.getApi().stop();
278
+ };
263
279
 
264
- function onShakeEnd(content, isLooped) {
265
- const {
266
- id: shakeId,
267
- parent: shakeParent
268
- } = content;
269
- if (shakeParent.id !== id) return;
270
- result[shakeId] = result[shakeId] || [];
271
- result[shakeId].push({ ...content,
272
- isLooped
273
- });
280
+ proto.getPostponed = function getPostponed(filterFn) {
281
+ return this[kElements].postponed.slice().reduce((result, msg) => {
282
+ const api = this._getChildApi(msg);
283
+
284
+ if (api) {
285
+ if (filterFn && !filterFn(api)) return result;
286
+ result.push(api);
274
287
  }
288
+
289
+ return result;
290
+ }, []);
291
+ };
292
+
293
+ proto.discard = function discard() {
294
+ this[kStatus] = 'discard';
295
+ return this[kActivityQ].queueMessage({
296
+ routingKey: 'execution.discard'
297
+ }, {
298
+ id: this.id,
299
+ type: this.type,
300
+ executionId: this.executionId
301
+ }, {
302
+ type: 'discard'
303
+ });
304
+ };
305
+
306
+ proto.getState = function getState() {
307
+ const {
308
+ children,
309
+ flows,
310
+ outboundMessageFlows,
311
+ associations
312
+ } = this[kElements];
313
+ return {
314
+ executionId: this.executionId,
315
+ stopped: this[kStopped],
316
+ completed: this[kCompleted],
317
+ status: this.status,
318
+ children: children.reduce((result, activity) => {
319
+ if (activity.placeholder) return result;
320
+ result.push(activity.getState());
321
+ return result;
322
+ }, []),
323
+ ...(flows.length && {
324
+ flows: flows.map(f => f.getState())
325
+ }),
326
+ ...(outboundMessageFlows.length && {
327
+ messageFlows: outboundMessageFlows.length && outboundMessageFlows.map(f => f.getState())
328
+ }),
329
+ ...(associations.length && {
330
+ associations: associations.map(f => f.getState())
331
+ })
332
+ };
333
+ };
334
+
335
+ proto.getActivities = function getActivities() {
336
+ return this[kElements].children.slice();
337
+ };
338
+
339
+ proto.getActivityById = function getActivityById(activityId) {
340
+ return this[kElements].children.find(child => child.id === activityId);
341
+ };
342
+
343
+ proto.getSequenceFlows = function getSequenceFlows() {
344
+ return this[kElements].flows.slice();
345
+ };
346
+
347
+ proto.getApi = function getApi(message) {
348
+ if (!message) return (0, _Api.ProcessApi)(this.broker, this[kExecuteMessage]);
349
+ const content = message.content;
350
+
351
+ if (content.executionId !== this.executionId) {
352
+ return this._getChildApi(message);
275
353
  }
276
354
 
277
- function stop() {
278
- getApi().stop();
355
+ const api = (0, _Api.ProcessApi)(this.broker, message);
356
+ const postponed = this[kElements].postponed;
357
+ const self = this;
358
+
359
+ api.getExecuting = function getExecuting() {
360
+ return postponed.reduce((result, msg) => {
361
+ const childApi = self._getChildApi(msg);
362
+
363
+ if (childApi) result.push(childApi);
364
+ return result;
365
+ }, []);
366
+ };
367
+
368
+ return api;
369
+ };
370
+
371
+ proto._start = function start() {
372
+ if (this[kElements].children.length === 0) {
373
+ return this._complete('completed');
374
+ }
375
+
376
+ this[kStatus] = 'start';
377
+ const executeContent = { ...this[kExecuteMessage].content,
378
+ state: this.status
379
+ };
380
+ this.broker.publish(this._exchangeName, 'execute.start', (0, _messageHelper.cloneContent)(executeContent));
381
+ const {
382
+ startActivities,
383
+ postponed,
384
+ detachedActivities
385
+ } = this[kElements];
386
+
387
+ if (startActivities.length > 1) {
388
+ for (const a of startActivities) a.shake();
279
389
  }
280
390
 
281
- function activate() {
282
- broker.subscribeTmp('api', '#', onApiMessage, {
391
+ for (const a of startActivities) a.init();
392
+
393
+ for (const a of startActivities) a.run();
394
+
395
+ postponed.splice(0);
396
+ detachedActivities.splice(0);
397
+ this[kActivityQ].assertConsumer(this[kMessageHandlers].onChildMessage, {
398
+ prefetch: 1000,
399
+ consumerTag: `_process-activity-${this.executionId}`
400
+ });
401
+ };
402
+
403
+ proto._activate = function activate() {
404
+ const {
405
+ onApiMessage,
406
+ onMessageFlowEvent,
407
+ onActivityEvent
408
+ } = this[kMessageHandlers];
409
+ this.broker.subscribeTmp('api', '#', onApiMessage, {
410
+ noAck: true,
411
+ consumerTag: `_process-api-consumer-${this.executionId}`,
412
+ priority: 200
413
+ });
414
+ const {
415
+ outboundMessageFlows,
416
+ flows,
417
+ associations,
418
+ startActivities,
419
+ triggeredByEvent,
420
+ children
421
+ } = this[kElements];
422
+
423
+ for (const flow of outboundMessageFlows) {
424
+ flow.activate();
425
+ flow.broker.subscribeTmp('event', '#', onMessageFlowEvent, {
426
+ consumerTag: '_process-message-consumer',
283
427
  noAck: true,
284
- consumerTag: `_process-api-consumer-${executionId}`,
285
428
  priority: 200
286
429
  });
287
- outboundMessageFlows.forEach(flow => {
288
- flow.activate();
289
- flow.broker.subscribeTmp('event', '#', onMessageFlowEvent, {
290
- consumerTag: '_process-message-consumer',
291
- noAck: true,
292
- priority: 200
293
- });
294
- });
295
- flows.forEach(flow => {
296
- flow.broker.subscribeTmp('event', '#', onActivityEvent, {
297
- consumerTag: '_process-flow-controller',
298
- noAck: true,
299
- priority: 200
300
- });
430
+ }
431
+
432
+ for (const flow of flows) {
433
+ flow.broker.subscribeTmp('event', '#', onActivityEvent, {
434
+ consumerTag: '_process-flow-controller',
435
+ noAck: true,
436
+ priority: 200
301
437
  });
302
- associations.forEach(association => {
303
- association.broker.subscribeTmp('event', '#', onActivityEvent, {
304
- consumerTag: '_process-association-controller',
305
- noAck: true,
306
- priority: 200
307
- });
438
+ }
439
+
440
+ for (const association of associations) {
441
+ association.broker.subscribeTmp('event', '#', onActivityEvent, {
442
+ consumerTag: '_process-association-controller',
443
+ noAck: true,
444
+ priority: 200
308
445
  });
309
- startActivities.splice(0);
310
- triggeredByEventActivities.splice(0);
311
- children.forEach(activity => {
312
- if (activity.placeholder) return;
313
- activity.activate(processExecution);
314
- activity.broker.subscribeTmp('event', '#', onActivityEvent, {
315
- noAck: true,
316
- consumerTag: '_process-activity-consumer',
317
- priority: 200
318
- });
319
- if (activity.isStart) startActivities.push(activity);
320
- if (activity.triggeredByEvent) triggeredByEventActivities.push(activity);
446
+ }
447
+
448
+ startActivities.splice(0);
449
+ triggeredByEvent.splice(0);
450
+
451
+ for (const activity of children) {
452
+ if (activity.placeholder) continue;
453
+ activity.activate(this);
454
+ activity.broker.subscribeTmp('event', '#', onActivityEvent, {
455
+ noAck: true,
456
+ consumerTag: '_process-activity-consumer',
457
+ priority: 200
321
458
  });
322
- activated = true;
323
-
324
- function onActivityEvent(routingKey, activityMessage) {
325
- const message = (0, _messageHelper.cloneMessage)(activityMessage);
326
- if (message.fields.redelivered && message.properties.persistent === false) return;
327
- const content = message.content;
328
- const parent = content.parent = content.parent || {};
329
- let delegate = message.properties.delegate;
330
- const shaking = message.properties.type === 'shake';
331
- const isDirectChild = content.parent.id === id;
332
-
333
- if (isDirectChild) {
334
- parent.executionId = executionId;
335
- } else {
336
- content.parent = (0, _messageHelper.pushParent)(parent, {
337
- id,
338
- type,
339
- executionId
340
- });
341
- }
459
+ if (activity.isStart) startActivities.push(activity);
460
+ if (activity.triggeredByEvent) triggeredByEvent.push(activity);
461
+ }
342
462
 
343
- if (delegate) delegate = onDelegateEvent(message);
344
- broker.publish('event', routingKey, content, { ...message.properties,
345
- delegate,
346
- mandatory: false
347
- });
348
- if (shaking) return onShookEnd(message);
349
- if (!isDirectChild) return;
350
- if (content.isAssociation) return;
351
-
352
- switch (routingKey) {
353
- case 'process.terminate':
354
- return activityQ.queueMessage({
355
- routingKey: 'execution.terminate'
356
- }, (0, _messageHelper.cloneContent)(content), {
357
- type: 'terminate',
358
- persistent: true
359
- });
463
+ this[kActivated] = true;
464
+ };
360
465
 
361
- case 'activity.stop':
362
- return;
363
- }
466
+ proto._deactivate = function deactivate() {
467
+ const broker = this.broker;
468
+ const executionId = this.executionId;
469
+ broker.cancel(`_process-api-consumer-${executionId}`);
470
+ broker.cancel(`_process-activity-${executionId}`);
471
+ const {
472
+ children,
473
+ flows,
474
+ associations,
475
+ outboundMessageFlows
476
+ } = this[kElements];
477
+
478
+ for (const activity of children) {
479
+ if (activity.placeholder) continue;
480
+ activity.broker.cancel('_process-activity-consumer');
481
+ activity.deactivate();
482
+ }
364
483
 
365
- activityQ.queueMessage(message.fields, (0, _messageHelper.cloneContent)(content), {
366
- persistent: true,
367
- ...message.properties
368
- });
369
- }
484
+ for (const flow of flows) {
485
+ flow.broker.cancel('_process-flow-controller');
370
486
  }
371
487
 
372
- function deactivate() {
373
- broker.cancel(`_process-api-consumer-${executionId}`);
374
- broker.cancel(`_process-activity-${executionId}`);
375
- children.forEach(activity => {
376
- if (activity.placeholder) return;
377
- activity.broker.cancel('_process-activity-consumer');
378
- activity.deactivate();
379
- });
380
- flows.forEach(flow => {
381
- flow.broker.cancel('_process-flow-controller');
382
- });
383
- associations.forEach(association => {
384
- association.broker.cancel('_process-association-controller');
385
- });
386
- outboundMessageFlows.forEach(flow => {
387
- flow.deactivate();
388
- flow.broker.cancel('_process-message-consumer');
389
- });
390
- activated = false;
391
- }
392
-
393
- function onDelegateEvent(message) {
394
- const eventType = message.properties.type;
395
- let delegate = true;
396
- const content = message.content;
397
- logger.debug(`<${executionName}> delegate`, eventType, content.message && content.message.id ? `event with id <${content.message.id}>` : 'anonymous event');
398
- triggeredByEventActivities.forEach(activity => {
399
- if (activity.getStartActivities({
400
- referenceId: content.message && content.message.id,
401
- referenceType: eventType
402
- }).length) {
403
- delegate = false;
404
- activity.run(content.message);
405
- }
406
- });
407
- getApi().sendApiMessage(eventType, content, {
408
- delegate: true
409
- });
410
- return delegate;
488
+ for (const association of associations) {
489
+ association.broker.cancel('_process-association-controller');
411
490
  }
412
491
 
413
- function onMessageFlowEvent(routingKey, message) {
414
- broker.publish('message', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
492
+ for (const flow of outboundMessageFlows) {
493
+ flow.deactivate();
494
+ flow.broker.cancel('_process-message-consumer');
415
495
  }
416
496
 
417
- function onChildMessage(routingKey, message) {
418
- const content = message.content;
419
- const isRedelivered = message.fields.redelivered;
420
- const {
421
- id: childId,
422
- type: activityType,
423
- isEnd
424
- } = content;
425
- const {
426
- persistent
427
- } = message.properties;
428
- if (isRedelivered && persistent === false) return message.ack();
497
+ this[kActivated] = false;
498
+ };
429
499
 
430
- switch (routingKey) {
431
- case 'execution.stop':
432
- message.ack();
433
- return stopExecution();
434
-
435
- case 'execution.terminate':
436
- message.ack();
437
- return terminate(message);
438
-
439
- case 'execution.discard':
440
- message.ack();
441
- return onDiscard(message);
442
-
443
- case 'activity.compensation.end':
444
- case 'flow.looped':
445
- case 'activity.leave':
446
- return onChildCompleted();
500
+ proto._onDelegateEvent = function onDelegateEvent(message) {
501
+ const eventType = message.properties.type;
502
+ let delegate = true;
503
+ const content = message.content;
504
+
505
+ if (content.message && content.message.id) {
506
+ this._debug(`delegate ${eventType} event with id <${content.message.id}>`);
507
+ } else {
508
+ this._debug(`delegate ${eventType} anonymous event`);
509
+ }
510
+
511
+ for (const activity of this[kElements].triggeredByEvent) {
512
+ if (activity.getStartActivities({
513
+ referenceId: content.message && content.message.id,
514
+ referenceType: eventType
515
+ }).length) {
516
+ delegate = false;
517
+ activity.run(content.message);
447
518
  }
519
+ }
448
520
 
449
- stateChangeMessage(true);
521
+ this.getApi().sendApiMessage(eventType, content, {
522
+ delegate: true
523
+ });
524
+ return delegate;
525
+ };
526
+
527
+ proto._onMessageFlowEvent = function onMessageFlowEvent(routingKey, message) {
528
+ this.broker.publish('message', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
529
+ };
530
+
531
+ proto._onActivityEvent = function onActivityEvent(routingKey, message) {
532
+ if (message.fields.redelivered && message.properties.persistent === false) return;
533
+ const content = message.content;
534
+ const parent = content.parent = content.parent || {};
535
+ let delegate = message.properties.delegate;
536
+ const shaking = message.properties.type === 'shake';
537
+ const isDirectChild = content.parent.id === this.id;
538
+
539
+ if (isDirectChild) {
540
+ parent.executionId = this.executionId;
541
+ } else {
542
+ content.parent = (0, _messageHelper.pushParent)(parent, {
543
+ id: this.id,
544
+ type: this.type,
545
+ executionId: this.executionId
546
+ });
547
+ }
450
548
 
451
- switch (routingKey) {
452
- case 'activity.detach':
453
- {
454
- detachedActivities.push((0, _messageHelper.cloneMessage)(message));
455
- break;
456
- }
549
+ if (delegate) delegate = this._onDelegateEvent(message);
550
+ this.broker.publish('event', routingKey, content, { ...message.properties,
551
+ delegate,
552
+ mandatory: false
553
+ });
554
+ if (shaking) return this._onShookEnd(message);
555
+ if (!isDirectChild) return;
556
+ if (content.isAssociation) return;
557
+
558
+ switch (routingKey) {
559
+ case 'process.terminate':
560
+ return this[kActivityQ].queueMessage({
561
+ routingKey: 'execution.terminate'
562
+ }, (0, _messageHelper.cloneContent)(content), {
563
+ type: 'terminate',
564
+ persistent: true
565
+ });
457
566
 
458
- case 'activity.discard':
459
- case 'activity.compensation.start':
460
- case 'activity.enter':
461
- {
462
- status = 'executing';
463
- popInbound();
464
- break;
465
- }
567
+ case 'activity.stop':
568
+ return;
569
+ }
466
570
 
467
- case 'flow.error':
468
- case 'activity.error':
469
- {
470
- if (isEventCaught()) {
471
- logger.debug(`<${executionName}> error was caught`);
472
- break;
473
- }
571
+ this[kActivityQ].queueMessage(message.fields, (0, _messageHelper.cloneContent)(content), {
572
+ persistent: true,
573
+ ...message.properties
574
+ });
575
+ };
474
576
 
475
- complete('error', {
476
- error: content.error
477
- });
478
- break;
479
- }
480
- }
577
+ proto._onChildMessage = function onChildMessage(routingKey, message) {
578
+ if (message.fields.redelivered && message.properties.persistent === false) return message.ack();
579
+ const content = message.content;
481
580
 
482
- function stateChangeMessage(postponeMessage = true) {
483
- const previousMsg = popPostponed(content);
484
- if (previousMsg) previousMsg.ack();
485
- if (postponeMessage) postponed.push(message);
486
- }
581
+ switch (routingKey) {
582
+ case 'execution.stop':
583
+ message.ack();
584
+ return this._stopExecution(message);
487
585
 
488
- function popInbound() {
489
- if (!content.inbound) return;
490
- content.inbound.forEach(trigger => {
491
- if (!trigger.isSequenceFlow) return;
492
- const msg = popPostponed(trigger, postponed);
493
- if (msg) msg.ack();
494
- });
495
- }
586
+ case 'execution.terminate':
587
+ message.ack();
588
+ return this._terminate(message);
496
589
 
497
- function popPostponed(byContent) {
498
- const postponedIdx = postponed.findIndex(msg => {
499
- if (msg.content.isSequenceFlow) return msg.content.sequenceId === byContent.sequenceId;
500
- return msg.content.executionId === byContent.executionId;
501
- });
502
- let postponedMsg;
590
+ case 'execution.discard':
591
+ message.ack();
592
+ return this._onDiscard(message);
503
593
 
504
- if (postponedIdx > -1) {
505
- postponedMsg = postponed.splice(postponedIdx, 1)[0];
594
+ case 'activity.compensation.end':
595
+ case 'flow.looped':
596
+ case 'activity.leave':
597
+ return this._onChildCompleted(message);
598
+ }
599
+
600
+ this._stateChangeMessage(message, true);
601
+
602
+ switch (routingKey) {
603
+ case 'activity.detach':
604
+ {
605
+ this[kElements].detachedActivities.push((0, _messageHelper.cloneMessage)(message));
606
+ break;
506
607
  }
507
608
 
508
- const detachedIdx = detachedActivities.findIndex(msg => msg.content.executionId === byContent.executionId);
509
- if (detachedIdx > -1) detachedActivities.splice(detachedIdx, 1);
510
- return postponedMsg;
511
- }
609
+ case 'activity.discard':
610
+ case 'activity.compensation.start':
611
+ case 'activity.enter':
612
+ {
613
+ this[kStatus] = 'executing';
614
+ if (!content.inbound) break;
615
+
616
+ for (const inbound of content.inbound) {
617
+ if (!inbound.isSequenceFlow) continue;
618
+
619
+ const inboundMessage = this._popPostponed(inbound);
620
+
621
+ if (inboundMessage) inboundMessage.ack();
622
+ }
512
623
 
513
- function onChildCompleted() {
514
- stateChangeMessage(false);
515
- if (isRedelivered) return message.ack();
516
- logger.debug(`<${executionName}> left <${childId}> (${activityType}), pending runs ${postponed.length}`, postponed.map(a => a.content.id));
517
- const postponedLength = postponed.length;
518
-
519
- if (!postponedLength) {
520
- message.ack();
521
- return complete('completed');
522
- } else if (postponedLength === detachedActivities.length) {
523
- getPostponed().forEach(api => api.discard());
524
- } else if (isEnd && startActivities.length) {
525
- discardPostponedIfNecessary();
624
+ break;
526
625
  }
527
- }
528
626
 
529
- function discardPostponedIfNecessary() {
530
- for (const p of postponed) {
531
- const postponedId = p.content.id;
532
- const startSequence = startSequences[postponedId];
533
-
534
- if (startSequence) {
535
- if (startSequence.content.sequence.some(({
536
- id: sid
537
- }) => sid === childId)) {
538
- getApi(p).discard();
539
- }
627
+ case 'activity.error':
628
+ {
629
+ const eventCaughtBy = this[kElements].postponed.find(msg => {
630
+ if (msg.fields.routingKey !== 'activity.catch') return;
631
+ return msg.content.source && msg.content.source.executionId === content.executionId;
632
+ });
633
+
634
+ if (eventCaughtBy) {
635
+ return this._debug('error was caught');
540
636
  }
637
+
638
+ return this._complete('error', {
639
+ error: content.error
640
+ });
541
641
  }
542
- }
642
+ }
643
+ };
543
644
 
544
- function stopExecution() {
545
- if (stopped) return;
546
- logger.debug(`<${executionName}> stop process execution (stop child executions ${postponed.length})`);
547
- getPostponed().forEach(api => {
548
- api.stop();
549
- });
550
- deactivate();
551
- stopped = true;
552
- return broker.publish(exchangeName, `execution.stopped.${executionId}`, { ...stateMessage.content,
553
- ...content
554
- }, {
555
- type: 'stopped',
556
- persistent: false
557
- });
558
- }
645
+ proto._stateChangeMessage = function stateChangeMessage(message, postponeMessage) {
646
+ const previousMsg = this._popPostponed(message.content);
559
647
 
560
- function onDiscard() {
561
- deactivate();
562
- const running = postponed.splice(0);
563
- logger.debug(`<${executionName}> discard process execution (discard child executions ${running.length})`);
564
- getSequenceFlows().forEach(flow => {
565
- flow.stop();
566
- });
567
- running.forEach(msg => {
568
- getApi(msg).discard();
569
- });
570
- activityQ.purge();
571
- return complete('discard');
572
- }
648
+ if (previousMsg) previousMsg.ack();
649
+ if (postponeMessage) this[kElements].postponed.push(message);
650
+ };
573
651
 
574
- function isEventCaught() {
575
- return postponed.find(msg => {
576
- if (msg.fields.routingKey !== 'activity.catch') return;
577
- return msg.content.source && msg.content.source.executionId === content.executionId;
578
- });
579
- }
652
+ proto._popPostponed = function popPostponed(byContent) {
653
+ const {
654
+ postponed,
655
+ detachedActivities
656
+ } = this[kElements];
657
+ const postponedIdx = postponed.findIndex(msg => {
658
+ if (msg.content.isSequenceFlow) return msg.content.sequenceId === byContent.sequenceId;
659
+ return msg.content.executionId === byContent.executionId;
660
+ });
661
+ let postponedMsg;
662
+
663
+ if (postponedIdx > -1) {
664
+ postponedMsg = postponed.splice(postponedIdx, 1)[0];
580
665
  }
581
666
 
582
- function onApiMessage(routingKey, message) {
583
- if (message.properties.delegate) {
584
- return delegateApiMessage();
585
- }
667
+ const detachedIdx = detachedActivities.findIndex(msg => msg.content.executionId === byContent.executionId);
668
+ if (detachedIdx > -1) detachedActivities.splice(detachedIdx, 1);
669
+ return postponedMsg;
670
+ };
586
671
 
587
- if (id !== message.content.id) {
588
- const child = getActivityById(message.content.id);
589
- if (!child) return null;
590
- return child.broker.publish('api', routingKey, message.content, message.properties);
591
- }
672
+ proto._onChildCompleted = function onChildCompleted(message) {
673
+ this._stateChangeMessage(message, false);
592
674
 
593
- if (executionId !== message.content.executionId) return;
675
+ if (message.fields.redelivered) return message.ack();
676
+ const {
677
+ id,
678
+ type,
679
+ isEnd
680
+ } = message.content;
681
+ const {
682
+ postponed,
683
+ detachedActivities,
684
+ startActivities
685
+ } = this[kElements];
686
+ const postponedCount = postponed.length;
594
687
 
595
- switch (message.properties.type) {
596
- case 'discard':
597
- return discard(message);
688
+ if (!postponedCount) {
689
+ this._debug(`left <${id}> (${type}), pending runs ${postponedCount}`);
598
690
 
599
- case 'stop':
600
- activityQ.queueMessage({
601
- routingKey: 'execution.stop'
602
- }, (0, _messageHelper.cloneContent)(message.content), {
603
- persistent: false
604
- });
605
- break;
606
- }
691
+ message.ack();
692
+ return this._complete('completed');
693
+ }
607
694
 
608
- function delegateApiMessage() {
609
- const {
610
- correlationId
611
- } = message.properties || (0, _shared.getUniqueId)(executionId);
612
- logger.debug(`<${executionName}> delegate api`, routingKey, `message to children, with correlationId <${correlationId}>`);
613
- let consumed = false;
614
- broker.subscribeTmp('event', 'activity.consumed', (_, msg) => {
615
- if (msg.properties.correlationId === correlationId) {
616
- consumed = true;
617
- logger.debug(`<${executionName}> delegated api message was consumed by`, msg.content ? msg.content.executionId : 'unknown');
618
- }
619
- }, {
620
- consumerTag: `_ct-delegate-${correlationId}`,
621
- noAck: true
622
- });
695
+ this._debug(`left <${id}> (${type}), pending runs ${postponedCount}, ${postponed.map(a => a.content.id).join(',')}`);
623
696
 
624
- for (const child of children) {
625
- if (child.placeholder) continue;
626
- child.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
627
- if (consumed) break;
628
- }
697
+ if (postponedCount === detachedActivities.length) {
698
+ for (const api of this.getPostponed()) api.discard();
629
699
 
630
- broker.cancel(`_ct-delegate-${correlationId}`);
631
- }
700
+ return;
632
701
  }
633
702
 
634
- function getPostponed(filterFn) {
635
- return postponed.slice().reduce((result, p) => {
636
- const api = getApi(p);
703
+ if (isEnd && startActivities.length) {
704
+ const startSequences = this[kElements].startSequences;
637
705
 
638
- if (api) {
639
- if (filterFn && !filterFn(api)) return result;
640
- result.push(api);
641
- }
706
+ for (const msg of postponed) {
707
+ const postponedId = msg.content.id;
708
+ const startSequence = startSequences[postponedId];
642
709
 
643
- return result;
644
- }, []);
710
+ if (startSequence) {
711
+ if (startSequence.content.sequence.some(({
712
+ id: sid
713
+ }) => sid === id)) {
714
+ this._getChildApi(msg).discard();
715
+ }
716
+ }
717
+ }
645
718
  }
719
+ };
646
720
 
647
- function complete(completionType, content = {}) {
648
- deactivate();
649
- logger.debug(`<${executionName}> process execution ${completionType}`);
650
- completed = true;
651
- if (status !== 'terminated') status = completionType;
652
- broker.deleteQueue(activityQ.name);
653
- return broker.publish(exchangeName, `execution.${completionType}.${executionId}`, { ...stateMessage.content,
654
- output: environment.output,
655
- ...content,
656
- state: completionType
657
- }, {
658
- type: completionType,
659
- mandatory: completionType === 'error'
660
- });
721
+ proto._stopExecution = function stopExecution(message) {
722
+ const postponedCount = this.postponedCount;
723
+
724
+ this._debug(`stop process execution (stop child executions ${postponedCount})`);
725
+
726
+ if (postponedCount) {
727
+ for (const api of this.getPostponed()) api.stop();
661
728
  }
662
729
 
663
- function discard() {
664
- status = 'discard';
665
- return activityQ.queueMessage({
666
- routingKey: 'execution.discard'
667
- }, {
668
- id,
669
- type,
670
- executionId
730
+ this._deactivate();
731
+
732
+ this[kStopped] = true;
733
+ return this.broker.publish(this._exchangeName, `execution.stopped.${this.executionId}`, { ...this[kExecuteMessage].content,
734
+ ...(message && message.content)
735
+ }, {
736
+ type: 'stopped',
737
+ persistent: false
738
+ });
739
+ };
740
+
741
+ proto._onDiscard = function onDiscard() {
742
+ this._deactivate();
743
+
744
+ const running = this[kElements].postponed.splice(0);
745
+
746
+ this._debug(`discard process execution (discard child executions ${running.length})`);
747
+
748
+ for (const flow of this.getSequenceFlows()) flow.stop();
749
+
750
+ for (const msg of running) this._getChildApi(msg).discard();
751
+
752
+ this[kActivityQ].purge();
753
+ return this._complete('discard');
754
+ };
755
+
756
+ proto._onApiMessage = function onApiMessage(routingKey, message) {
757
+ const executionId = this.executionId;
758
+ const broker = this.broker;
759
+
760
+ if (message.properties.delegate) {
761
+ const correlationId = message.properties.correlationId || (0, _shared.getUniqueId)(executionId);
762
+
763
+ this._debug(`delegate api ${routingKey} message to children, with correlationId <${correlationId}>`);
764
+
765
+ let consumed = false;
766
+ broker.subscribeTmp('event', 'activity.consumed', (_, msg) => {
767
+ if (msg.properties.correlationId === correlationId) {
768
+ consumed = true;
769
+
770
+ this._debug(`delegated api message was consumed by ${msg.content ? msg.content.executionId : 'unknown'}`);
771
+ }
671
772
  }, {
672
- type: 'discard'
773
+ consumerTag: `_ct-delegate-${correlationId}`,
774
+ noAck: true
673
775
  });
674
- }
675
776
 
676
- function terminate(message) {
677
- status = 'terminated';
678
- logger.debug(`<${executionName}> terminating process execution`);
679
- const running = postponed.splice(0);
680
- getSequenceFlows().forEach(flow => {
681
- flow.stop();
682
- });
683
- running.forEach(msg => {
684
- const {
685
- id: postponedId,
686
- isSequenceFlow
687
- } = msg.content;
688
- if (postponedId === message.content.id) return;
689
- if (isSequenceFlow) return;
690
- getApi(msg).stop();
691
- msg.ack();
692
- });
693
- activityQ.purge();
694
- }
695
-
696
- function getState() {
697
- return {
698
- executionId,
699
- stopped,
700
- completed,
701
- status,
702
- children: children.reduce((result, activity) => {
703
- if (activity.placeholder) return result;
704
- result.push(activity.getState());
705
- return result;
706
- }, []),
707
- flows: flows.map(f => f.getState()),
708
- messageFlows: outboundMessageFlows.map(f => f.getState()),
709
- associations: associations.map(f => f.getState())
710
- };
711
- }
777
+ for (const child of this[kElements].children) {
778
+ if (child.placeholder) continue;
779
+ child.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
780
+ if (consumed) break;
781
+ }
712
782
 
713
- function getActivities() {
714
- return children.slice();
783
+ return broker.cancel(`_ct-delegate-${correlationId}`);
715
784
  }
716
785
 
717
- function getActivityById(activityId) {
718
- return children.find(child => child.id === activityId);
786
+ if (this.id !== message.content.id) {
787
+ const child = this.getActivityById(message.content.id);
788
+ if (!child) return null;
789
+ return child.broker.publish('api', routingKey, message.content, message.properties);
719
790
  }
720
791
 
721
- function getFlowById(flowId) {
722
- return flows.find(f => f.id === flowId);
723
- }
792
+ if (this.executionId !== message.content.executionId) return;
724
793
 
725
- function getAssociationById(associationId) {
726
- return associations.find(a => a.id === associationId);
727
- }
794
+ switch (message.properties.type) {
795
+ case 'discard':
796
+ return this.discard(message);
728
797
 
729
- function getMessageFlowById(flowId) {
730
- return outboundMessageFlows.find(f => f.id === flowId);
798
+ case 'stop':
799
+ this[kActivityQ].queueMessage({
800
+ routingKey: 'execution.stop'
801
+ }, (0, _messageHelper.cloneContent)(message.content), {
802
+ persistent: false
803
+ });
804
+ break;
731
805
  }
806
+ };
732
807
 
733
- function getChildById(childId) {
734
- return getActivityById(childId) || getFlowById(childId);
735
- }
808
+ proto._complete = function complete(completionType, content) {
809
+ this._deactivate();
736
810
 
737
- function getSequenceFlows() {
738
- return flows.slice();
739
- }
811
+ this._debug(`process execution ${completionType}`);
740
812
 
741
- function getApi(message) {
742
- if (!message) return (0, _Api.ProcessApi)(broker, stateMessage);
743
- const content = message.content;
813
+ this[kCompleted] = true;
814
+ if (this.status !== 'terminated') this[kStatus] = completionType;
815
+ const broker = this.broker;
816
+ this[kActivityQ].delete();
817
+ return broker.publish(this._exchangeName, `execution.${completionType}.${this.executionId}`, (0, _messageHelper.cloneContent)(this[kExecuteMessage].content, {
818
+ output: { ...this.environment.output
819
+ },
820
+ ...content,
821
+ state: completionType
822
+ }), {
823
+ type: completionType,
824
+ mandatory: completionType === 'error'
825
+ });
826
+ };
744
827
 
745
- if (content.executionId !== executionId) {
746
- return getChildApi(message);
747
- }
828
+ proto._terminate = function terminate(message) {
829
+ this[kStatus] = 'terminated';
748
830
 
749
- const api = (0, _Api.ProcessApi)(broker, message);
831
+ this._debug('terminating process execution');
750
832
 
751
- api.getExecuting = function getExecuting() {
752
- return postponed.reduce((result, msg) => {
753
- if (msg.content.executionId === content.executionId) return result;
754
- result.push(getApi(msg));
755
- return result;
756
- }, []);
757
- };
833
+ const running = this[kElements].postponed.splice(0);
758
834
 
759
- return api;
760
- }
835
+ for (const flow of this.getSequenceFlows()) flow.stop();
761
836
 
762
- function getChildApi(message) {
763
- const content = message.content;
764
- let api = getApiByChildId(content.id);
765
- if (api) return api;
766
- if (!content.parent) return;
767
- api = getApiByChildId(content.parent.id);
768
- if (api) return api;
769
- if (!content.parent.path) return;
837
+ for (const msg of running) {
838
+ const {
839
+ id: postponedId,
840
+ isSequenceFlow
841
+ } = msg.content;
842
+ if (postponedId === message.content.id) continue;
843
+ if (isSequenceFlow) continue;
770
844
 
771
- for (let i = 0; i < content.parent.path.length; i++) {
772
- api = getApiByChildId(content.parent.path[i].id);
773
- if (api) return api;
774
- }
845
+ this._getChildApi(msg).stop();
775
846
 
776
- function getApiByChildId(childId) {
777
- const child = getChildById(childId);
778
- if (!child) return;
779
- return child.getApi(message);
780
- }
847
+ msg.ack();
781
848
  }
782
849
 
783
- function onShookEnd(message) {
784
- const routingKey = message.fields.routingKey;
785
- if (routingKey !== 'activity.shake.end') return;
786
- startSequences[message.content.id] = (0, _messageHelper.cloneMessage)(message);
787
- }
850
+ this[kActivityQ].purge();
851
+ };
852
+
853
+ proto._getFlowById = function getFlowById(flowId) {
854
+ return this[kElements].flows.find(f => f.id === flowId);
855
+ };
788
856
 
789
- function prepare() {
790
- executionName = `${executionId} (${id})`;
857
+ proto._getAssociationById = function getAssociationById(associationId) {
858
+ return this[kElements].associations.find(a => a.id === associationId);
859
+ };
860
+
861
+ proto._getMessageFlowById = function getMessageFlowById(flowId) {
862
+ return this[kElements].outboundMessageFlows.find(f => f.id === flowId);
863
+ };
864
+
865
+ proto._getChildById = function getChildById(childId) {
866
+ return this.getActivityById(childId) || this._getFlowById(childId);
867
+ };
868
+
869
+ proto._getChildApi = function getChildApi(message) {
870
+ const content = message.content;
871
+
872
+ let child = this._getChildById(content.id);
873
+
874
+ if (child) return child.getApi(message);
875
+ if (!content.parent) return;
876
+ child = this._getChildById(content.parent.id);
877
+ if (child) return child.getApi(message);
878
+ if (!content.parent.path) return;
879
+
880
+ for (const pp of content.parent.path) {
881
+ child = this._getChildById(pp.id, message);
882
+ if (child) return child.getApi(message);
791
883
  }
792
- }
884
+ };
885
+
886
+ proto._onShookEnd = function onShookEnd(message) {
887
+ const routingKey = message.fields.routingKey;
888
+ if (routingKey !== 'activity.shake.end') return;
889
+ this[kElements].startSequences[message.content.id] = (0, _messageHelper.cloneMessage)(message);
890
+ };
891
+
892
+ proto._debug = function debugMessage(logMessage) {
893
+ this[kParent].logger.debug(`<${this.executionId} (${this.id})> ${logMessage}`);
894
+ };