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