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
@@ -5,507 +5,809 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = DefinitionExecution;
7
7
 
8
+ var _getPropertyValue = _interopRequireDefault(require("../getPropertyValue"));
9
+
8
10
  var _Api = require("../Api");
9
11
 
10
- var _messageHelper = require("../messageHelper");
12
+ var _shared = require("../shared");
11
13
 
12
- var _getPropertyValue = _interopRequireDefault(require("../getPropertyValue"));
14
+ var _messageHelper = require("../messageHelper");
13
15
 
14
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
17
 
16
- function DefinitionExecution(definition) {
17
- const {
18
- id,
19
- type,
20
- broker,
21
- logger,
22
- environment
23
- } = definition;
24
- const processes = definition.getProcesses();
25
- const processIds = processes.map(({
26
- id: childId
27
- }) => childId);
28
- let executableProcesses = definition.getExecutableProcesses();
29
- const postponed = [];
18
+ const kActivated = Symbol.for('activated');
19
+ const kProcessesQ = Symbol.for('processesQ');
20
+ const kCompleted = Symbol.for('completed');
21
+ const kExecuteMessage = Symbol.for('executeMessage');
22
+ const kMessageHandlers = Symbol.for('messageHandlers');
23
+ const kParent = Symbol.for('definition');
24
+ const kProcesses = Symbol.for('processes');
25
+ const kStatus = Symbol.for('status');
26
+ const kStopped = Symbol.for('stopped');
27
+
28
+ function DefinitionExecution(definition, context) {
29
+ const broker = definition.broker;
30
+ this[kParent] = definition;
31
+ this.id = definition.id;
32
+ this.type = definition.type;
33
+ this.broker = broker;
34
+ const environment = this.environment = definition.environment;
35
+ this.context = context;
36
+ const processes = context.getProcesses();
37
+ const ids = [];
38
+ const executable = [];
39
+
40
+ for (const bp of processes) {
41
+ bp.environment.assignVariables(environment.variables);
42
+ bp.environment.assignSettings(environment.settings);
43
+ ids.push(bp.id);
44
+ if (bp.isExecutable) executable.push(bp);
45
+ }
46
+
47
+ this[kProcesses] = {
48
+ processes,
49
+ running: [],
50
+ ids,
51
+ executable,
52
+ postponed: []
53
+ };
30
54
  broker.assertExchange('execution', 'topic', {
31
55
  autoDelete: false,
32
56
  durable: true
33
57
  });
34
- let activityQ,
35
- status = 'init',
36
- executionId,
37
- stopped,
38
- activated,
39
- initMessage,
40
- completed = false;
41
- const definitionExecution = {
42
- id,
43
- type,
44
- broker,
58
+ this.executionId = undefined;
59
+ this[kCompleted] = false;
60
+ this[kStopped] = false;
61
+ this[kActivated] = false;
62
+ this[kStatus] = 'init';
63
+ this[kProcessesQ] = undefined;
64
+ this[kMessageHandlers] = {
65
+ onApiMessage: this._onApiMessage.bind(this),
66
+ onCallActivity: this._onCallActivity.bind(this),
67
+ onCancelCallActivity: this._onCancelCallActivity.bind(this),
68
+ onChildEvent: this._onChildEvent.bind(this),
69
+ onDelegateMessage: this._onDelegateMessage.bind(this),
70
+ onMessageOutbound: this._onMessageOutbound.bind(this),
71
+ onProcessMessage: this._onProcessMessage.bind(this)
72
+ };
73
+ }
45
74
 
46
- get environment() {
47
- return environment;
48
- },
75
+ const proto = DefinitionExecution.prototype;
76
+ Object.defineProperty(proto, 'stopped', {
77
+ enumerable: true,
49
78
 
50
- get executionId() {
51
- return executionId;
52
- },
79
+ get() {
80
+ return this[kStopped];
81
+ }
53
82
 
54
- get completed() {
55
- return completed;
56
- },
83
+ });
84
+ Object.defineProperty(proto, 'completed', {
85
+ enumerable: true,
57
86
 
58
- get status() {
59
- return status;
60
- },
87
+ get() {
88
+ return this[kCompleted];
89
+ }
61
90
 
62
- get stopped() {
63
- return stopped;
64
- },
91
+ });
92
+ Object.defineProperty(proto, 'status', {
93
+ enumerable: true,
65
94
 
66
- get postponedCount() {
67
- return postponed.length;
68
- },
95
+ get() {
96
+ return this[kStatus];
97
+ }
69
98
 
70
- get isRunning() {
71
- if (activated) return true;
72
- return false;
73
- },
99
+ });
100
+ Object.defineProperty(proto, 'processes', {
101
+ enumerable: true,
74
102
 
75
- processes,
76
- createMessage,
77
- getApi,
78
- getState,
79
- getPostponed,
80
- execute,
81
- resume,
82
- recover,
83
- stop
84
- };
85
- return definitionExecution;
86
-
87
- function execute(executeMessage) {
88
- if (!executeMessage) throw new Error('Definition execution requires message');
89
- const {
90
- content,
91
- fields
92
- } = executeMessage;
93
- if (!content || !content.executionId) throw new Error('Definition execution requires execution id');
94
- const isRedelivered = fields.redelivered;
95
- executionId = content.executionId;
96
- initMessage = (0, _messageHelper.cloneMessage)(executeMessage, {
97
- executionId,
98
- state: 'start'
99
- });
100
- stopped = false;
101
- activityQ = broker.assertQueue(`execute-${executionId}-q`, {
102
- durable: true,
103
- autoDelete: false
104
- });
103
+ get() {
104
+ return this[kProcesses].running;
105
+ }
105
106
 
106
- if (isRedelivered) {
107
- return resume();
108
- }
107
+ });
108
+ Object.defineProperty(proto, 'postponedCount', {
109
+ get() {
110
+ return this[kProcesses].postponed.length;
111
+ }
109
112
 
110
- if (content.processId) {
111
- const startWithProcess = definition.getProcessById(content.processId);
112
- if (startWithProcess) executableProcesses = [startWithProcess];
113
- }
113
+ });
114
+ Object.defineProperty(proto, 'isRunning', {
115
+ get() {
116
+ return this[kActivated];
117
+ }
114
118
 
115
- logger.debug(`<${executionId} (${id})> execute definition`);
116
- activate();
117
- start();
118
- return true;
119
+ });
120
+
121
+ proto.execute = function execute(executeMessage) {
122
+ if (!executeMessage) throw new Error('Definition execution requires message');
123
+ const content = executeMessage.content;
124
+ const executionId = this.executionId = content.executionId;
125
+ if (!executionId) throw new Error('Definition execution requires execution id');
126
+ this[kExecuteMessage] = (0, _messageHelper.cloneMessage)(executeMessage, {
127
+ executionId,
128
+ state: 'start'
129
+ });
130
+ this[kStopped] = false;
131
+ this[kProcessesQ] = this.broker.assertQueue(`execute-${executionId}-q`, {
132
+ durable: true,
133
+ autoDelete: false
134
+ });
135
+
136
+ if (executeMessage.fields.redelivered) {
137
+ return this.resume();
119
138
  }
120
139
 
121
- function resume() {
122
- logger.debug(`<${executionId} (${id})> resume`, status, 'definition execution');
123
- if (completed) return complete('completed');
124
- activate();
125
- postponed.splice(0);
126
- activityQ.consume(onProcessMessage, {
127
- prefetch: 1000,
128
- consumerTag: `_definition-activity-${executionId}`
129
- });
130
- if (completed) return complete('completed');
140
+ const {
141
+ running,
142
+ executable
143
+ } = this[kProcesses];
131
144
 
132
- switch (status) {
133
- case 'init':
134
- return start();
145
+ if (content.processId) {
146
+ const startWithProcess = this.getProcessById(content.processId);
135
147
 
136
- case 'executing':
137
- {
138
- if (!postponed.length) return complete('completed');
139
- break;
140
- }
148
+ if (startWithProcess) {
149
+ executable.splice(0);
150
+ executable.push(startWithProcess);
141
151
  }
142
-
143
- processes.forEach(p => p.resume());
144
152
  }
145
153
 
146
- function start() {
147
- if (!processes.length) {
148
- return publishCompletionMessage('completed');
149
- }
154
+ this._debug('execute definition');
155
+
156
+ running.push(...executable);
157
+
158
+ this._activate(executable);
150
159
 
151
- if (!executableProcesses.length) {
152
- return complete('error', {
153
- error: new Error('No executable process')
154
- });
160
+ this._start();
161
+
162
+ return true;
163
+ };
164
+
165
+ proto.resume = function resume() {
166
+ this._debug(`resume ${this[kStatus]} definition execution`);
167
+
168
+ if (this[kCompleted]) return this._complete('completed');
169
+ const {
170
+ running,
171
+ postponed
172
+ } = this[kProcesses];
173
+
174
+ this._activate(running);
175
+
176
+ postponed.splice(0);
177
+ this[kProcessesQ].consume(this[kMessageHandlers].onProcessMessage, {
178
+ prefetch: 1000,
179
+ consumerTag: `_definition-activity-${this.executionId}`
180
+ });
181
+ if (this[kCompleted]) return;
182
+
183
+ for (const bp of running) bp.resume();
184
+ };
185
+
186
+ proto.recover = function recover(state) {
187
+ if (!state) return this;
188
+ this.executionId = state.executionId;
189
+ this[kStopped] = state.stopped;
190
+ this[kCompleted] = state.completed;
191
+ this[kStatus] = state.status;
192
+
193
+ this._debug(`recover ${this[kStatus]} definition execution`);
194
+
195
+ const running = this[kProcesses].running;
196
+ running.splice(0);
197
+ const ids = [];
198
+
199
+ for (const bpState of state.processes) {
200
+ const bpid = bpState.id;
201
+ let bp;
202
+
203
+ if (ids.indexOf(bpid) > -1) {
204
+ bp = this.context.getNewProcessById(bpid);
205
+ } else {
206
+ bp = this.getProcessById(bpid);
155
207
  }
156
208
 
157
- status = 'start';
158
- executableProcesses.forEach(p => p.init());
159
- executableProcesses.forEach(p => p.run());
160
- postponed.splice(0);
161
- activityQ.assertConsumer(onProcessMessage, {
162
- prefetch: 1000,
163
- consumerTag: `_definition-activity-${executionId}`
164
- });
209
+ if (!bp) return;
210
+ ids.push(bpid);
211
+ bp.recover(bpState);
212
+ running.push(bp);
165
213
  }
166
214
 
167
- function recover(state) {
168
- if (!state) return definitionExecution;
169
- executionId = state.executionId;
170
- stopped = state.stopped;
171
- completed = state.completed;
172
- status = state.status;
173
- logger.debug(`<${executionId} (${id})> recover`, status, 'definition execution');
174
- state.processes.forEach(processState => {
175
- const instance = definition.getProcessById(processState.id);
176
- if (!instance) return;
177
- instance.recover(processState);
178
- });
179
- return definitionExecution;
215
+ return this;
216
+ };
217
+
218
+ proto.stop = function stop() {
219
+ this.getApi().stop();
220
+ };
221
+
222
+ proto.getProcesses = function getProcesses() {
223
+ const {
224
+ running,
225
+ processes
226
+ } = this[kProcesses];
227
+ const result = running.slice();
228
+
229
+ for (const bp of processes) {
230
+ if (!result.find(runningBp => bp.id === runningBp.id)) result.push(bp);
180
231
  }
181
232
 
182
- function stop() {
183
- getApi().stop();
233
+ return result;
234
+ };
235
+
236
+ proto.getProcessById = function getProcessById(processId) {
237
+ return this.getProcesses().find(bp => bp.id === processId);
238
+ };
239
+
240
+ proto.getProcessesById = function getProcessesById(processId) {
241
+ return this.getProcesses().filter(bp => bp.id === processId);
242
+ };
243
+
244
+ proto.getProcessByExecutionId = function getProcessByExecutionId(processExecutionId) {
245
+ const running = this[kProcesses].running;
246
+ return running.find(bp => bp.executionId === processExecutionId);
247
+ };
248
+
249
+ proto.getRunningProcesses = function getRunningProcesses() {
250
+ const running = this[kProcesses].running;
251
+ return running.filter(bp => bp.executionId);
252
+ };
253
+
254
+ proto.getExecutableProcesses = function getExecutableProcesses() {
255
+ return this[kProcesses].executable.slice();
256
+ };
257
+
258
+ proto.getState = function getState() {
259
+ return {
260
+ executionId: this.executionId,
261
+ stopped: this[kStopped],
262
+ completed: this[kCompleted],
263
+ status: this[kStatus],
264
+ processes: this[kProcesses].running.map(bp => bp.getState())
265
+ };
266
+ };
267
+
268
+ proto.getApi = function getApi(apiMessage) {
269
+ if (!apiMessage) apiMessage = this[kExecuteMessage] || {
270
+ content: this._createMessage()
271
+ };
272
+ const content = apiMessage.content;
273
+
274
+ if (content.executionId !== this.executionId) {
275
+ return this._getProcessApi(apiMessage);
184
276
  }
185
277
 
186
- function activate() {
187
- broker.subscribeTmp('api', '#', onApiMessage, {
188
- noAck: true,
189
- consumerTag: '_definition-api-consumer'
190
- });
191
- processes.forEach(p => {
192
- p.broker.subscribeTmp('message', 'message.outbound', onMessageOutbound, {
193
- noAck: true,
194
- consumerTag: '_definition-outbound-message-consumer'
195
- });
196
- p.broker.subscribeTmp('event', 'activity.signal', onDelegateMessage, {
197
- noAck: true,
198
- consumerTag: '_definition-signal-consumer',
199
- priority: 200
200
- });
201
- p.broker.subscribeTmp('event', 'activity.message', onDelegateMessage, {
202
- noAck: true,
203
- consumerTag: '_definition-message-consumer',
204
- priority: 200
205
- });
206
- p.broker.subscribeTmp('event', '#', onEvent, {
207
- noAck: true,
208
- consumerTag: '_definition-activity-consumer',
209
- priority: 100
210
- });
211
- });
212
- activated = true;
213
-
214
- function onEvent(routingKey, originalMessage) {
215
- const message = (0, _messageHelper.cloneMessage)(originalMessage);
216
- const content = message.content;
217
- const parent = content.parent = content.parent || {};
218
- const isDirectChild = processIds.indexOf(content.id) > -1;
219
-
220
- if (isDirectChild) {
221
- parent.executionId = executionId;
222
- } else {
223
- content.parent = (0, _messageHelper.pushParent)(parent, {
224
- id,
225
- type,
226
- executionId
227
- });
228
- }
278
+ const api = (0, _Api.DefinitionApi)(this.broker, apiMessage);
279
+ const postponed = this[kProcesses].postponed;
280
+ const self = this;
229
281
 
230
- broker.publish('event', routingKey, content, { ...message.properties,
231
- mandatory: false
232
- });
233
- if (!isDirectChild) return;
234
- activityQ.queueMessage(message.fields, (0, _messageHelper.cloneContent)(content), message.properties);
235
- }
282
+ api.getExecuting = function getExecuting() {
283
+ return postponed.reduce((result, msg) => {
284
+ const bpApi = self._getProcessApi(msg);
285
+
286
+ if (bpApi) result.push(bpApi);
287
+ return result;
288
+ }, []);
289
+ };
290
+
291
+ return api;
292
+ };
293
+
294
+ proto.getPostponed = function getPostponed(...args) {
295
+ const running = this[kProcesses].running;
296
+ return running.reduce((result, p) => {
297
+ result = result.concat(p.getPostponed(...args));
298
+ return result;
299
+ }, []);
300
+ };
301
+
302
+ proto._start = function start() {
303
+ const {
304
+ ids,
305
+ executable,
306
+ postponed
307
+ } = this[kProcesses];
308
+
309
+ if (!ids.length) {
310
+ return this._complete('completed');
236
311
  }
237
312
 
238
- function deactivate() {
239
- broker.cancel('_definition-api-consumer');
240
- broker.cancel(`_definition-activity-${executionId}`);
241
- processes.forEach(p => {
242
- p.broker.cancel('_definition-outbound-message-consumer');
243
- p.broker.cancel('_definition-activity-consumer');
244
- p.broker.cancel('_definition-signal-consumer');
245
- p.broker.cancel('_definition-message-consumer');
313
+ if (!executable.length) {
314
+ return this._complete('error', {
315
+ error: new Error('No executable process')
246
316
  });
247
- activated = false;
248
317
  }
249
318
 
250
- function onProcessMessage(routingKey, message) {
251
- const content = message.content;
252
- const isRedelivered = message.fields.redelivered;
253
- const {
254
- id: childId,
255
- type: activityType,
256
- executionId: childExecutionId
257
- } = content;
258
- if (isRedelivered && message.properties.persistent === false) return;
259
-
260
- switch (routingKey) {
261
- case 'execution.stop':
262
- {
263
- if (childExecutionId === executionId) {
264
- message.ack();
265
- return onStopped();
266
- }
319
+ this[kStatus] = 'start';
267
320
 
268
- break;
269
- }
321
+ for (const bp of executable) bp.init();
270
322
 
271
- case 'process.leave':
272
- {
273
- return onChildCompleted();
274
- }
275
- }
276
-
277
- stateChangeMessage(true);
323
+ for (const bp of executable) bp.run();
278
324
 
279
- switch (routingKey) {
280
- case 'process.discard':
281
- case 'process.enter':
282
- status = 'executing';
283
- break;
325
+ postponed.splice(0);
326
+ this[kProcessesQ].assertConsumer(this[kMessageHandlers].onProcessMessage, {
327
+ prefetch: 1000,
328
+ consumerTag: `_definition-activity-${this.executionId}`
329
+ });
330
+ };
284
331
 
285
- case 'process.error':
286
- {
287
- processes.slice().forEach(p => {
288
- if (p.id !== childId) p.stop();
289
- });
290
- complete('error', {
291
- error: content.error
292
- });
293
- break;
294
- }
295
- }
332
+ proto._activate = function activate(processList) {
333
+ this.broker.subscribeTmp('api', '#', this[kMessageHandlers].onApiMessage, {
334
+ noAck: true,
335
+ consumerTag: '_definition-api-consumer'
336
+ });
296
337
 
297
- function stateChangeMessage(postponeMessage = true) {
298
- const previousMsg = popPostponed(childId);
299
- if (previousMsg) previousMsg.ack();
300
- if (postponeMessage) postponed.push(message);
301
- }
338
+ for (const bp of processList) this._activateProcess(bp);
302
339
 
303
- function popPostponed(postponedId) {
304
- const idx = postponed.findIndex(msg => msg.content.id === postponedId);
340
+ this[kActivated] = true;
341
+ };
305
342
 
306
- if (idx > -1) {
307
- return postponed.splice(idx, 1)[0];
308
- }
309
- }
310
-
311
- function onChildCompleted() {
312
- stateChangeMessage(false);
313
- if (isRedelivered) return message.ack();
314
- logger.debug(`<${executionId} (${id})> left <${childId}> (${activityType}), pending runs ${postponed.length}`);
343
+ proto._activateProcess = function activateProcess(bp) {
344
+ const handlers = this[kMessageHandlers];
345
+ bp.broker.subscribeTmp('message', 'message.outbound', handlers.onMessageOutbound, {
346
+ noAck: true,
347
+ consumerTag: '_definition-outbound-message-consumer'
348
+ });
349
+ bp.broker.subscribeTmp('event', 'activity.signal', handlers.onDelegateMessage, {
350
+ noAck: true,
351
+ consumerTag: '_definition-signal-consumer',
352
+ priority: 200
353
+ });
354
+ bp.broker.subscribeTmp('event', 'activity.message', handlers.onDelegateMessage, {
355
+ noAck: true,
356
+ consumerTag: '_definition-message-consumer',
357
+ priority: 200
358
+ });
359
+ bp.broker.subscribeTmp('event', 'activity.call', handlers.onCallActivity, {
360
+ noAck: true,
361
+ consumerTag: '_definition-call-consumer',
362
+ priority: 200
363
+ });
364
+ bp.broker.subscribeTmp('event', 'activity.call.cancel', handlers.onCancelCallActivity, {
365
+ noAck: true,
366
+ consumerTag: '_definition-call-cancel-consumer',
367
+ priority: 200
368
+ });
369
+ bp.broker.subscribeTmp('event', '#', handlers.onChildEvent, {
370
+ noAck: true,
371
+ consumerTag: '_definition-activity-consumer',
372
+ priority: 100
373
+ });
374
+ };
375
+
376
+ proto._onChildEvent = function onChildEvent(routingKey, originalMessage) {
377
+ const message = (0, _messageHelper.cloneMessage)(originalMessage);
378
+ const content = message.content;
379
+ const parent = content.parent = content.parent || {};
380
+ const isDirectChild = this[kProcesses].ids.indexOf(content.id) > -1;
381
+
382
+ if (isDirectChild) {
383
+ parent.executionId = this.executionId;
384
+ } else {
385
+ content.parent = (0, _messageHelper.pushParent)(parent, this);
386
+ }
315
387
 
316
- if (!postponed.length) {
388
+ this.broker.publish('event', routingKey, content, { ...message.properties,
389
+ mandatory: false
390
+ });
391
+ if (!isDirectChild) return;
392
+ this[kProcessesQ].queueMessage(message.fields, (0, _messageHelper.cloneContent)(content), message.properties);
393
+ };
394
+
395
+ proto._deactivate = function deactivate() {
396
+ this.broker.cancel('_definition-api-consumer');
397
+ this.broker.cancel(`_definition-activity-${this.executionId}`);
398
+
399
+ for (const bp of this[kProcesses].running) this._deactivateProcess(bp);
400
+
401
+ this[kActivated] = false;
402
+ };
403
+
404
+ proto._deactivateProcess = function deactivateProcess(bp) {
405
+ bp.broker.cancel('_definition-outbound-message-consumer');
406
+ bp.broker.cancel('_definition-activity-consumer');
407
+ bp.broker.cancel('_definition-signal-consumer');
408
+ bp.broker.cancel('_definition-message-consumer');
409
+ bp.broker.cancel('_definition-call-consumer');
410
+ bp.broker.cancel('_definition-call-cancel-consumer');
411
+ };
412
+
413
+ proto._onProcessMessage = function onProcessMessage(routingKey, message) {
414
+ const content = message.content;
415
+ const isRedelivered = message.fields.redelivered;
416
+ const {
417
+ id: childId,
418
+ inbound
419
+ } = content;
420
+ if (isRedelivered && message.properties.persistent === false) return;
421
+
422
+ switch (routingKey) {
423
+ case 'execution.stop':
424
+ {
317
425
  message.ack();
318
- complete('completed');
426
+ return this._onStopped(message);
319
427
  }
320
- }
321
428
 
322
- function onStopped() {
323
- logger.debug(`<${executionId} (${id})> stop definition execution (stop process executions ${postponed.length})`);
324
- activityQ.close();
325
- deactivate();
326
- processes.slice().forEach(p => {
327
- p.stop();
328
- });
329
- stopped = true;
330
- return broker.publish('execution', `execution.stopped.${executionId}`, { ...initMessage.content,
331
- ...content
332
- }, {
333
- type: 'stopped',
334
- persistent: false
335
- });
336
- }
429
+ case 'process.leave':
430
+ {
431
+ return this._onProcessCompleted(message);
432
+ }
337
433
  }
338
434
 
339
- function onApiMessage(routingKey, message) {
340
- const messageType = message.properties.type;
341
- const delegate = message.properties.delegate;
435
+ this._stateChangeMessage(message, true);
342
436
 
343
- if (delegate && id === message.content.id) {
344
- const referenceId = (0, _getPropertyValue.default)(message, 'content.message.id');
437
+ switch (routingKey) {
438
+ case 'process.enter':
439
+ this[kStatus] = 'executing';
440
+ break;
345
441
 
346
- for (const bp of processes) {
347
- if (bp.isRunning) continue;
442
+ case 'process.discarded':
443
+ {
444
+ if (inbound && inbound.length) {
445
+ const calledFrom = inbound[0];
348
446
 
349
- if (bp.getStartActivities({
350
- referenceId,
351
- referenceType: messageType
352
- }).length) {
353
- logger.debug(`<${executionId} (${id})> start <${bp.id}>`);
354
- bp.run();
447
+ this._getProcessApi({
448
+ content: calledFrom
449
+ }).cancel({
450
+ executionId: calledFrom.executionId
451
+ });
355
452
  }
453
+
454
+ break;
356
455
  }
357
- }
358
456
 
359
- if (delegate) {
360
- for (const bp of processes) {
361
- bp.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
457
+ case 'process.end':
458
+ {
459
+ if (inbound && inbound.length) {
460
+ const calledFrom = inbound[0];
461
+
462
+ this._getProcessApi({
463
+ content: calledFrom
464
+ }).signal({
465
+ executionId: calledFrom.executionId,
466
+ output: { ...content.output
467
+ }
468
+ });
469
+ } else {
470
+ Object.assign(this.environment.output, content.output);
471
+ }
472
+
473
+ break;
362
474
  }
363
- }
364
475
 
365
- if (executionId !== message.content.executionId) return;
476
+ case 'process.error':
477
+ {
478
+ if (inbound && inbound.length) {
479
+ const calledFrom = inbound[0];
480
+
481
+ this._getProcessApi({
482
+ content: calledFrom
483
+ }).sendApiMessage('error', {
484
+ executionId: calledFrom.executionId,
485
+ error: content.error
486
+ }, {
487
+ mandatory: true,
488
+ type: 'error'
489
+ });
490
+ } else {
491
+ for (const bp of this[kProcesses].running.slice()) {
492
+ if (bp.id !== childId) bp.stop();
493
+ }
494
+
495
+ this._complete('error', {
496
+ error: content.error
497
+ });
498
+ }
366
499
 
367
- switch (messageType) {
368
- case 'stop':
369
- activityQ.queueMessage({
370
- routingKey: 'execution.stop'
371
- }, (0, _messageHelper.cloneContent)(message.content), {
372
- persistent: false
373
- });
374
500
  break;
375
- }
501
+ }
376
502
  }
503
+ };
377
504
 
378
- function getState() {
379
- return {
380
- executionId,
381
- stopped,
382
- completed,
383
- status,
384
- processes: processes.map(p => p.getState())
385
- };
386
- }
505
+ proto._stateChangeMessage = function stateChangeMessage(message, postponeMessage) {
506
+ let previousMsg;
507
+ const postponed = this[kProcesses].postponed;
508
+ const idx = postponed.findIndex(msg => msg.content.executionId === message.content.executionId);
387
509
 
388
- function getPostponed(...args) {
389
- return processes.reduce((result, p) => {
390
- result = result.concat(p.getPostponed(...args));
391
- return result;
392
- }, []);
510
+ if (idx > -1) {
511
+ previousMsg = postponed.splice(idx, 1)[0];
393
512
  }
394
513
 
395
- function complete(completionType, content, options) {
396
- deactivate();
397
- logger.debug(`<${executionId} (${id})> definition execution ${completionType} in ${Date.now() - initMessage.properties.timestamp}ms`);
398
- if (!content) content = createMessage();
399
- completed = true;
400
- if (status !== 'terminated') status = completionType;
401
- broker.deleteQueue(activityQ.name);
402
- return broker.publish('execution', `execution.${completionType}.${executionId}`, { ...initMessage.content,
403
- output: environment.output,
404
- ...content,
405
- state: completionType
406
- }, {
407
- type: completionType,
408
- mandatory: completionType === 'error',
409
- ...options
410
- });
514
+ if (previousMsg) previousMsg.ack();
515
+ if (postponeMessage) postponed.push(message);
516
+ };
517
+
518
+ proto._onProcessCompleted = function onProcessCompleted(message) {
519
+ this._stateChangeMessage(message, false);
520
+
521
+ if (message.fields.redelivered) return message.ack();
522
+ const {
523
+ id,
524
+ executionId,
525
+ type,
526
+ inbound
527
+ } = message.content;
528
+
529
+ this._debug(`left <${executionId} (${id})> (${type}), pending runs ${this.postponedCount}`);
530
+
531
+ if (inbound && inbound.length) {
532
+ const bp = this._removeProcessByExecutionId(executionId);
533
+
534
+ this._deactivateProcess(bp);
411
535
  }
412
536
 
413
- function onMessageOutbound(routingKey, message) {
414
- const content = message.content;
415
- const {
416
- target,
417
- source
418
- } = content;
419
- logger.debug(`<${executionId} (${id})> conveying message from <${source.processId}.${source.id}> to`, target.id ? `<${target.processId}.${target.id}>` : `<${target.processId}>`);
420
- const targetProcess = getProcessById(target.processId);
421
- targetProcess.sendMessage(message);
537
+ if (!this.postponedCount) {
538
+ message.ack();
539
+
540
+ this._complete('completed');
422
541
  }
542
+ };
423
543
 
424
- function onDelegateMessage(routingKey, executeMessage) {
425
- const content = executeMessage.content;
426
- const messageType = executeMessage.properties.type;
427
- const delegateMessage = executeMessage.content.message;
428
- const reference = definition.getElementById(delegateMessage.id);
429
- const message = reference && reference.resolve(executeMessage);
430
- logger.debug(`<${executionId} (${id})>`, reference ? `${messageType} <${delegateMessage.id}>` : `anonymous ${messageType}`, `event received from <${content.parent.id}.${content.id}>. Delegating.`);
431
- getApi().sendApiMessage(messageType, {
432
- message: message,
433
- originalMessage: content.message
434
- }, {
435
- delegate: true,
436
- type: messageType
437
- });
438
- broker.publish('event', `definition.${messageType}`, createMessage({
439
- message: message && (0, _messageHelper.cloneContent)(message)
440
- }), {
441
- type: messageType
544
+ proto._onStopped = function onStopped(message) {
545
+ const running = this[kProcesses].running;
546
+
547
+ this._debug(`stop definition execution (stop process executions ${running.length})`);
548
+
549
+ this[kProcessesQ].close();
550
+
551
+ for (const bp of running.slice()) bp.stop();
552
+
553
+ this._deactivate();
554
+
555
+ this[kStopped] = true;
556
+ return this.broker.publish('execution', `execution.stopped.${this.executionId}`, (0, _messageHelper.cloneContent)(this[kExecuteMessage].content, { ...message.content
557
+ }), {
558
+ type: 'stopped',
559
+ persistent: false
560
+ });
561
+ };
562
+
563
+ proto._onApiMessage = function onApiMessage(routingKey, message) {
564
+ const messageType = message.properties.type;
565
+ const delegate = message.properties.delegate;
566
+
567
+ if (delegate && this.id === message.content.id) {
568
+ const referenceId = (0, _getPropertyValue.default)(message, 'content.message.id');
569
+
570
+ this._startProcessesByMessage({
571
+ referenceId,
572
+ referenceType: messageType
442
573
  });
443
574
  }
444
575
 
445
- function getProcessById(processId) {
446
- return processes.find(p => p.id === processId);
576
+ if (delegate) {
577
+ for (const bp of this[kProcesses].running.slice()) {
578
+ bp.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
579
+ }
447
580
  }
448
581
 
449
- function publishCompletionMessage(completionType, content) {
450
- deactivate();
451
- logger.debug(`<${executionId} (${id})> ${completionType}`);
452
- if (!content) content = createMessage();
453
- return broker.publish('execution', `execution.${completionType}.${executionId}`, content, {
454
- type: completionType
582
+ if (this.executionId !== message.content.executionId) return;
583
+
584
+ if (messageType === 'stop') {
585
+ this[kProcessesQ].queueMessage({
586
+ routingKey: 'execution.stop'
587
+ }, (0, _messageHelper.cloneContent)(message.content), {
588
+ persistent: false
455
589
  });
456
590
  }
591
+ };
457
592
 
458
- function createMessage(content = {}) {
459
- return {
460
- id,
461
- type,
462
- executionId,
463
- status,
464
- ...content
465
- };
466
- }
593
+ proto._startProcessesByMessage = function startProcessesByMessage(reference) {
594
+ const {
595
+ processes: bps,
596
+ running
597
+ } = this[kProcesses];
598
+ if (bps.length < 2) return;
599
+
600
+ for (const bp of bps) {
601
+ if (bp.isExecutable) continue;
602
+ if (!bp.getStartActivities(reference).length) continue;
467
603
 
468
- function getApi(apiMessage) {
469
- if (!apiMessage) apiMessage = initMessage || {
470
- content: createMessage()
471
- };
472
- const content = apiMessage.content;
604
+ if (!bp.executionId) {
605
+ this._debug(`start <${bp.id}> by <${reference.referenceId}> (${reference.referenceType})`);
473
606
 
474
- if (content.executionId !== executionId) {
475
- return getProcessApi(apiMessage);
607
+ this._activateProcess(bp);
608
+
609
+ running.push(bp);
610
+ bp.init();
611
+ bp.run();
612
+ if (reference.referenceType === 'message') return;
613
+ continue;
476
614
  }
477
615
 
478
- const api = (0, _Api.DefinitionApi)(broker, apiMessage);
616
+ this._debug(`start new <${bp.id}> by <${reference.referenceId}> (${reference.referenceType})`);
617
+
618
+ const targetProcess = this.context.getNewProcessById(bp.id);
479
619
 
480
- api.getExecuting = function getExecuting() {
481
- return postponed.reduce((result, msg) => {
482
- if (msg.content.executionId === content.executionId) return result;
483
- result.push(getApi(msg));
484
- return result;
485
- }, []);
486
- };
620
+ this._activateProcess(targetProcess);
487
621
 
488
- return api;
622
+ running.push(targetProcess);
623
+ targetProcess.init();
624
+ targetProcess.run();
625
+ if (reference.referenceType === 'message') return;
489
626
  }
627
+ };
490
628
 
491
- function getProcessApi(message) {
492
- const content = message.content;
493
- let api = getApiByProcessId(content.id);
494
- if (api) return api;
495
- if (!content.parent) return;
496
- api = getApiByProcessId(content.parent.id);
497
- if (api) return api;
498
- if (!content.parent.path) return;
629
+ proto._onMessageOutbound = function onMessageOutbound(routingKey, message) {
630
+ const content = message.content;
631
+ const {
632
+ target,
633
+ source
634
+ } = content;
635
+
636
+ this._debug(`conveying message from <${source.processId}.${source.id}> to`, target.id ? `<${target.processId}.${target.id}>` : `<${target.processId}>`);
499
637
 
500
- for (let i = 0; i < content.parent.path.length; i++) {
501
- api = getApiByProcessId(content.parent.path[i].id);
502
- if (api) return api;
638
+ const targetProcesses = this.getProcessesById(target.processId);
639
+ if (!targetProcesses.length) return;
640
+ let targetProcess, found;
641
+
642
+ for (const bp of targetProcesses) {
643
+ if (!bp.executionId) {
644
+ targetProcess = bp;
645
+ continue;
503
646
  }
504
647
 
505
- function getApiByProcessId(parentId) {
506
- const processInstance = getProcessById(parentId);
507
- if (!processInstance) return;
508
- return processInstance.getApi(message);
648
+ bp.sendMessage(message);
649
+ found = true;
650
+ }
651
+
652
+ if (found) return;
653
+ targetProcess = targetProcess || this.context.getNewProcessById(target.processId);
654
+
655
+ this._activateProcess(targetProcess);
656
+
657
+ this[kProcesses].running.push(targetProcess);
658
+ targetProcess.init();
659
+ targetProcess.run();
660
+ targetProcess.sendMessage(message);
661
+ };
662
+
663
+ proto._onCallActivity = function onCallActivity(routingKey, message) {
664
+ const content = message.content;
665
+ const {
666
+ calledElement,
667
+ id: fromId,
668
+ executionId: fromExecutionId,
669
+ name: fromName,
670
+ parent: fromParent
671
+ } = content;
672
+ if (!calledElement) return;
673
+ const bpExecutionId = `${(0, _shared.brokerSafeId)(calledElement)}_${fromExecutionId}`;
674
+
675
+ if (content.isRecovered) {
676
+ if (this.getProcessByExecutionId(bpExecutionId)) return;
677
+ }
678
+
679
+ const targetProcess = this.context.getNewProcessById(calledElement, {
680
+ settings: {
681
+ calledFrom: (0, _messageHelper.cloneContent)({
682
+ id: fromId,
683
+ name: fromName,
684
+ executionId: content.executionId,
685
+ parent: content.parent
686
+ })
509
687
  }
688
+ });
689
+ if (!targetProcess) return;
690
+
691
+ this._debug(`call from <${fromParent.id}.${fromId}> to <${calledElement}>`);
692
+
693
+ this._activateProcess(targetProcess);
694
+
695
+ this[kProcesses].running.push(targetProcess);
696
+ targetProcess.init(bpExecutionId);
697
+ targetProcess.run({
698
+ inbound: [(0, _messageHelper.cloneContent)(content)]
699
+ });
700
+ };
701
+
702
+ proto._onCancelCallActivity = function onCancelCallActivity(routingKey, message) {
703
+ const {
704
+ calledElement,
705
+ id: fromId,
706
+ executionId: fromExecutionId,
707
+ parent: fromParent
708
+ } = message.content;
709
+ if (!calledElement) return;
710
+ const bpExecutionId = `${(0, _shared.brokerSafeId)(calledElement)}_${fromExecutionId}`;
711
+ const targetProcess = this.getProcessByExecutionId(bpExecutionId);
712
+ if (!targetProcess) return;
713
+
714
+ this._debug(`cancel call from <${fromParent.id}.${fromId}> to <${calledElement}>`);
715
+
716
+ targetProcess.getApi().discard();
717
+ };
718
+
719
+ proto._onDelegateMessage = function onDelegateMessage(routingKey, executeMessage) {
720
+ const content = executeMessage.content;
721
+ const messageType = executeMessage.properties.type;
722
+ const delegateMessage = executeMessage.content.message;
723
+ const reference = this.context.getActivityById(delegateMessage.id);
724
+ const message = reference && reference.resolve(executeMessage);
725
+
726
+ this._debug(`<${reference ? `${messageType} ${delegateMessage.id}>` : `anonymous ${messageType}`} event received from <${content.parent.id}.${content.id}>. Delegating.`);
727
+
728
+ this.getApi().sendApiMessage(messageType, {
729
+ source: {
730
+ id: content.id,
731
+ executionId: content.executionId,
732
+ type: content.type,
733
+ parent: (0, _messageHelper.cloneParent)(content.parent)
734
+ },
735
+ message,
736
+ originalMessage: content.message
737
+ }, {
738
+ delegate: true,
739
+ type: messageType
740
+ });
741
+ this.broker.publish('event', `definition.${messageType}`, this._createMessage({
742
+ message: message && (0, _messageHelper.cloneContent)(message)
743
+ }), {
744
+ type: messageType
745
+ });
746
+ };
747
+
748
+ proto._removeProcessByExecutionId = function removeProcessByExecutionId(processExecutionId) {
749
+ const running = this[kProcesses].running;
750
+ const idx = running.findIndex(p => p.executionId === processExecutionId);
751
+ if (idx === -1) return;
752
+ return running.splice(idx, 1)[0];
753
+ };
754
+
755
+ proto._complete = function complete(completionType, content, options) {
756
+ this._deactivate();
757
+
758
+ const stateMessage = this[kExecuteMessage];
759
+
760
+ this._debug(`definition execution ${completionType} in ${Date.now() - stateMessage.properties.timestamp}ms`);
761
+
762
+ if (!content) content = this._createMessage();
763
+ this[kCompleted] = true;
764
+ this[kStatus] = completionType;
765
+ this.broker.deleteQueue(this[kProcessesQ].name);
766
+ return this.broker.publish('execution', `execution.${completionType}.${this.executionId}`, { ...stateMessage.content,
767
+ output: { ...this.environment.output
768
+ },
769
+ ...content,
770
+ state: completionType
771
+ }, {
772
+ type: completionType,
773
+ mandatory: completionType === 'error',
774
+ ...options
775
+ });
776
+ };
777
+
778
+ proto._createMessage = function createMessage(content = {}) {
779
+ return {
780
+ id: this.id,
781
+ type: this.type,
782
+ executionId: this.executionId,
783
+ status: this[kStatus],
784
+ ...content
785
+ };
786
+ };
787
+
788
+ proto._getProcessApi = function getProcessApi(message) {
789
+ const content = message.content;
790
+
791
+ let api = this._getProcessApiByExecutionId(content.executionId, message);
792
+
793
+ if (api) return api;
794
+ if (!content.parent) return;
795
+ api = this._getProcessApiByExecutionId(content.parent.executionId, message);
796
+ if (api) return api;
797
+ if (!content.parent.path) return;
798
+
799
+ for (const pp of content.parent.path) {
800
+ api = this._getProcessApiByExecutionId(pp.executionId, message);
801
+ if (api) return api;
510
802
  }
511
- }
803
+ };
804
+
805
+ proto._getProcessApiByExecutionId = function getProcessApiByExecutionId(parentExecutionId, message) {
806
+ const processInstance = this.getProcessByExecutionId(parentExecutionId);
807
+ if (!processInstance) return;
808
+ return processInstance.getApi(message);
809
+ };
810
+
811
+ proto._debug = function debug(logMessage) {
812
+ this[kParent].logger.debug(`<${this.executionId} (${this.id})> ${logMessage}`);
813
+ };