bpmn-elements 6.0.1 → 8.0.1

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 +341 -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 +1105 -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 +16 -16
  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 +914 -776
  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
@@ -10,25 +10,22 @@ var _Errors = require("../error/Errors");
10
10
  var _messageHelper = require("../messageHelper");
11
11
 
12
12
  function LoopCharacteristics(activity, loopCharacteristics) {
13
- const {
14
- id,
15
- broker,
16
- environment
17
- } = activity;
18
- const {
19
- batchSize = 50
20
- } = environment.settings;
13
+ this.activity = activity;
14
+ this.loopCharacteristics = loopCharacteristics;
21
15
  const {
22
16
  type = 'LoopCharacteristics',
23
17
  behaviour = {}
24
18
  } = loopCharacteristics;
19
+ this.type = type;
25
20
  const {
26
21
  isSequential = false,
27
- collection: collectionExpression,
28
- elementVariable = 'item'
22
+ collection
29
23
  } = behaviour;
24
+ this.isSequential = isSequential;
25
+ this.collection = collection;
30
26
  let completionCondition, startCondition, loopCardinality;
31
27
  if ('loopCardinality' in behaviour) loopCardinality = behaviour.loopCardinality;else if ('loopMaximum' in behaviour) loopCardinality = behaviour.loopMaximum;
28
+ this.loopCardinality = loopCardinality;
32
29
 
33
30
  if (behaviour.loopCondition) {
34
31
  if (behaviour.testBefore) startCondition = behaviour.loopCondition;else completionCondition = behaviour.loopCondition;
@@ -38,344 +35,326 @@ function LoopCharacteristics(activity, loopCharacteristics) {
38
35
  completionCondition = behaviour.completionCondition;
39
36
  }
40
37
 
41
- const loopType = getLoopType();
42
- if (!loopType) return;
38
+ if (collection) {
39
+ this.loopType = 'collection';
40
+ this.elementVariable = behaviour.elementVariable || 'item';
41
+ } else if (completionCondition) this.loopType = 'complete condition';else if (startCondition) this.loopType = 'start condition';else if (loopCardinality) this.loopType = 'cardinality';
42
+
43
+ this.characteristics = null;
44
+ this.execution = null;
45
+ }
46
+
47
+ LoopCharacteristics.prototype.execute = function execute(executeMessage) {
48
+ if (!executeMessage) throw new TypeError('LoopCharacteristics execution requires message');
49
+ const chr = this.characteristics = this.characteristics || new Characteristics(this.activity, this.loopCharacteristics, executeMessage);
50
+ if (chr.cardinality === 0) return chr.complete();
51
+ const execution = this.isSequential ? new SequentialLoopCharacteristics(this.activity, chr) : new ParallelLoopCharacteristics(this.activity, chr);
52
+ return execution.execute(executeMessage);
53
+ };
54
+
55
+ function SequentialLoopCharacteristics(activity, characteristics) {
56
+ this.activity = activity;
57
+ this.id = activity.id;
58
+ this.characteristics = characteristics;
59
+ }
60
+
61
+ SequentialLoopCharacteristics.prototype.execute = function execute(executeMessage) {
43
62
  const {
44
- debug
45
- } = environment.Logger(type.toLowerCase());
46
- const executeConsumerTag = '_execute-q-multi-instance-tag';
47
- broker.cancel(executeConsumerTag);
48
- const apiConsumerTag = '_api-multi-instance-tag';
49
- broker.cancel(apiConsumerTag);
50
- let loopSettings;
51
- const characteristicsApi = {
52
- type,
53
- loopType,
54
- collection: collectionExpression,
55
- elementVariable,
56
- isSequential,
57
- loopCardinality,
58
- execute
59
- };
60
- return characteristicsApi;
63
+ routingKey: executeRoutingKey,
64
+ redelivered: isRedelivered
65
+ } = executeMessage.fields || {};
66
+ const chr = this.characteristics;
61
67
 
62
- function getLoopType() {
63
- if (collectionExpression) return 'collection';
64
- if (completionCondition) return 'complete condition';
65
- if (startCondition) return 'start condition';
66
- if (loopCardinality) return 'cardinality';
68
+ if (!chr.cardinality && !chr.startCondition && !chr.completionCondition) {
69
+ throw new _Errors.RunError(`<${this.id}> cardinality, collection, or condition is required in sequential loops`, executeMessage);
67
70
  }
68
71
 
69
- function execute(executeMessage) {
70
- if (!executeMessage) throw new Error('LoopCharacteristics execution requires message');
71
- const {
72
- routingKey: executeRoutingKey,
73
- redelivered: isRedelivered
74
- } = executeMessage.fields || {};
75
- const {
76
- executionId: parentExecutionId
77
- } = executeMessage.content;
78
- if (!getCharacteristics()) return;
79
-
80
- try {
81
- return isSequential ? executeSequential() : executeParallel();
82
- } catch (err) {
83
- return activity.emitFatal(new _Errors.ActivityError(err.message, executeMessage, err), executeMessage.content);
84
- }
72
+ let startIndex = 0;
85
73
 
86
- function executeSequential() {
87
- const {
88
- cardinality,
89
- getContent: getStartContent
90
- } = getCharacteristics();
91
- if (cardinality === 0) return complete();
92
- if (!cardinality && !startCondition && !completionCondition) return activity.emitFatal(new _Errors.ActivityError(`<${id}> cardinality, collection, or condition is required in sequential loops`, executeMessage), getStartContent());
93
- let startIndex = 0;
94
-
95
- if (isRedelivered && executeRoutingKey === 'execute.iteration.next') {
96
- startIndex = executeMessage.content.index;
97
- }
98
-
99
- subscribe(onCompleteMessage);
100
- return startNext(startIndex, isRedelivered);
101
-
102
- function startNext(index, ignoreIfExecuting) {
103
- const content = next(index);
104
- if (!content) return;
105
- const characteristics = getCharacteristics();
106
-
107
- if (startCondition && isConditionMet(startCondition, {
108
- content
109
- })) {
110
- debug(`<${parentExecutionId} (${id})> start condition met`);
111
- return;
112
- }
113
-
114
- debug(`<${content.executionId} (${id})>`, ignoreIfExecuting ? 'resume' : 'start', `sequential iteration index ${content.index}`);
115
- broker.publish('execution', 'execute.iteration.next', { ...content,
116
- ...characteristics.getContent(),
117
- index,
118
- preventComplete: true,
119
- output: characteristics.output.slice(),
120
- state: 'iteration.next'
121
- });
122
- broker.publish('execution', 'execute.start', { ...content,
123
- ignoreIfExecuting
124
- });
125
- return content;
126
- }
127
-
128
- function onCompleteMessage(_, message) {
129
- const {
130
- content
131
- } = message;
132
- const loopOutput = getCharacteristics().output;
133
- if (content.output !== undefined) loopOutput[content.index] = content.output;
134
- broker.publish('execution', 'execute.iteration.completed', { ...message.content,
135
- ...getCharacteristics().getContent(),
136
- preventComplete: true,
137
- output: loopOutput.slice(),
138
- state: 'iteration.completed'
139
- });
140
-
141
- if (isConditionMet(completionCondition, message, loopOutput)) {
142
- debug(`<${parentExecutionId} (${id})> complete condition met`);
143
- } else if (startNext(content.index + 1)) return;
144
-
145
- debug(`<${parentExecutionId} (${id})> sequential loop completed`);
146
- return complete(content);
147
- }
148
-
149
- function complete(content) {
150
- stop();
151
- const {
152
- getContent,
153
- output
154
- } = getCharacteristics();
155
- return broker.publish('execution', 'execute.completed', { ...content,
156
- ...getContent(),
157
- output
158
- });
159
- }
160
- }
74
+ if (isRedelivered && executeRoutingKey === 'execute.iteration.next') {
75
+ startIndex = executeMessage.content.index;
76
+ }
161
77
 
162
- function executeParallel() {
163
- const {
164
- cardinality,
165
- getContent: getStartContent
166
- } = getCharacteristics();
167
- if (cardinality === 0) return complete();
168
- if (!cardinality) return activity.emitFatal(new _Errors.ActivityError(`<${id}> cardinality or collection is required in parallel loops`, executeMessage), getStartContent());
169
- let index = 0,
170
- running = 0;
171
-
172
- if (isRedelivered) {
173
- if (!isNaN(executeMessage.content.index)) index = executeMessage.content.index;
174
- if (!isNaN(executeMessage.content.running)) running = executeMessage.content.running;
175
- }
176
-
177
- subscribe(onCompleteMessage);
178
- if (isRedelivered) return;
179
- return startBatch();
180
-
181
- function startBatch() {
182
- const {
183
- output: loopOutput,
184
- getContent
185
- } = getCharacteristics();
186
- const batch = [];
187
- let startContent = next(index);
188
-
189
- do {
190
- debug(`<${parentExecutionId} (${id})> start parallel iteration index ${index}`);
191
- batch.push(startContent);
192
- running++;
193
- index++;
194
-
195
- if (index >= cardinality || running >= batchSize) {
196
- break;
197
- }
198
- } while (startContent = next(index));
199
-
200
- broker.publish('execution', 'execute.iteration.batch', { ...getContent(),
201
- index,
202
- running,
203
- output: loopOutput,
204
- preventComplete: true
205
- });
206
-
207
- for (const content of batch) {
208
- broker.publish('execution', 'execute.start', content);
209
- }
210
- }
211
-
212
- function onCompleteMessage(_, message) {
213
- const {
214
- content
215
- } = message;
216
- const {
217
- output: loopOutput
218
- } = getCharacteristics();
219
- if (content.output !== undefined) loopOutput[content.index] = content.output;
220
- running--;
221
- broker.publish('execution', 'execute.iteration.completed', { ...content,
222
- ...getCharacteristics().getContent(),
223
- index,
224
- running,
225
- output: loopOutput,
226
- state: 'iteration.completed',
227
- preventComplete: true
228
- });
229
-
230
- if (running <= 0 && !next(index)) {
231
- return complete(content);
232
- }
233
-
234
- if (isConditionMet(completionCondition, message)) {
235
- return complete(content);
236
- }
237
-
238
- if (running <= 0) {
239
- running = 0;
240
- startBatch();
241
- }
242
- }
243
-
244
- function complete(content) {
245
- stop();
246
- const {
247
- getContent,
248
- output
249
- } = getCharacteristics();
250
- return broker.publish('execution', 'execute.completed', { ...content,
251
- ...getContent(),
252
- output
253
- });
254
- }
255
- }
78
+ chr.subscribe(this._onCompleteMessage.bind(this));
79
+ return this._startNext(startIndex, isRedelivered);
80
+ };
256
81
 
257
- function next(index) {
258
- const executionId = `${parentExecutionId}_${index}`;
259
- const {
260
- cardinality,
261
- collection,
262
- parent,
263
- getContent
264
- } = getCharacteristics();
265
- const content = { ...getContent(),
266
- isRootScope: undefined,
267
- executionId,
268
- isMultiInstance: true,
269
- index,
270
- parent
271
- };
272
- if (isComplete(content)) return;
273
-
274
- if (collection) {
275
- content[elementVariable] = collection[index];
276
- }
277
-
278
- return content;
279
-
280
- function isComplete() {
281
- if (cardinality > 0 && index >= cardinality) return true;
282
- if (collection && index >= collection.length) return true;
283
- }
284
- }
82
+ SequentialLoopCharacteristics.prototype._startNext = function startNext(index, ignoreIfExecuting) {
83
+ const chr = this.characteristics;
84
+ const content = chr.next(index);
85
+ if (!content) return;
285
86
 
286
- function getCharacteristics() {
287
- if (loopSettings) return loopSettings;
288
- const collection = getCollection();
289
- const cardinality = getCardinality(collection);
290
- const messageContent = { ...(0, _messageHelper.cloneContent)(executeMessage.content),
291
- loopCardinality: cardinality,
292
- isSequential,
293
- output: undefined
294
- };
295
-
296
- if (cardinality !== undefined && isNaN(cardinality) || cardinality < 0) {
297
- return activity.emitFatal(new _Errors.ActivityError(`<${id}> invalid loop cardinality >${cardinality}<`, executeMessage), messageContent);
298
- }
299
-
300
- const output = executeMessage.content.output || [];
301
- const parent = (0, _messageHelper.unshiftParent)(executeMessage.content.parent, executeMessage.content);
302
- loopSettings = {
303
- cardinality,
304
- collection,
305
- messageContent,
306
- output,
307
- parent,
308
-
309
- getContent() {
310
- return (0, _messageHelper.cloneContent)(messageContent);
311
- }
312
-
313
- };
314
- return loopSettings;
87
+ if (chr.isStartConditionMet({
88
+ content
89
+ })) {
90
+ chr.debug('start condition met');
91
+ return;
92
+ }
93
+
94
+ chr.debug(`${ignoreIfExecuting ? 'resume' : 'start'} sequential iteration index ${content.index}`);
95
+ const broker = this.activity.broker;
96
+ broker.publish('execution', 'execute.iteration.next', { ...content,
97
+ ...chr.getContent(),
98
+ index,
99
+ preventComplete: true,
100
+ output: chr.output.slice(),
101
+ state: 'iteration.next'
102
+ });
103
+ broker.publish('execution', 'execute.start', { ...content,
104
+ ignoreIfExecuting
105
+ });
106
+ return content;
107
+ };
108
+
109
+ SequentialLoopCharacteristics.prototype._onCompleteMessage = function onCompleteMessage(_, message) {
110
+ const {
111
+ content
112
+ } = message;
113
+ const chr = this.characteristics;
114
+ const loopOutput = chr.output;
115
+ if (content.output !== undefined) loopOutput[content.index] = content.output;
116
+ this.activity.broker.publish('execution', 'execute.iteration.completed', { ...message.content,
117
+ ...chr.getContent(),
118
+ preventComplete: true,
119
+ output: loopOutput.slice(),
120
+ state: 'iteration.completed'
121
+ });
122
+
123
+ if (chr.isCompletionConditionMet(message, loopOutput)) {
124
+ chr.debug('complete condition met');
125
+ } else if (this._startNext(content.index + 1)) return;
126
+
127
+ chr.debug('sequential loop completed');
128
+ return chr.complete(content);
129
+ };
130
+
131
+ function ParallelLoopCharacteristics(activity, characteristics) {
132
+ this.activity = activity;
133
+ this.id = activity.id;
134
+ this.characteristics = characteristics;
135
+ this.running = 0;
136
+ this.index = 0;
137
+ }
138
+
139
+ ParallelLoopCharacteristics.prototype.execute = function execute(executeMessage) {
140
+ const chr = this.characteristics;
141
+ if (!chr.cardinality) throw new _Errors.RunError(`<${this.id}> cardinality or collection is required in parallel loops`, executeMessage);
142
+ const isRedelivered = executeMessage.fields.redelivered;
143
+
144
+ if (isRedelivered) {
145
+ if (!isNaN(executeMessage.content.index)) this.index = executeMessage.content.index;
146
+ if (!isNaN(executeMessage.content.running)) this.running = executeMessage.content.running;
147
+ }
148
+
149
+ chr.subscribe(this._onCompleteMessage.bind(this));
150
+ if (isRedelivered) return;
151
+ return this._startBatch();
152
+ };
153
+
154
+ ParallelLoopCharacteristics.prototype._startBatch = function startBatch() {
155
+ const chr = this.characteristics;
156
+ const cardinality = chr.cardinality;
157
+ const batch = [];
158
+ let startContent = chr.next(this.index);
159
+
160
+ do {
161
+ chr.debug(`start parallel iteration index ${this.index}`);
162
+ batch.push(startContent);
163
+ this.running++;
164
+ this.index++;
165
+
166
+ if (this.index >= cardinality || this.running >= chr.batchSize) {
167
+ break;
315
168
  }
169
+ } while (startContent = chr.next(this.index));
170
+
171
+ const broker = this.activity.broker;
172
+ broker.publish('execution', 'execute.iteration.batch', { ...chr.getContent(),
173
+ index: this.index,
174
+ running: this.running,
175
+ output: chr.output,
176
+ preventComplete: true
177
+ });
178
+
179
+ for (const content of batch) {
180
+ broker.publish('execution', 'execute.start', content);
181
+ }
182
+ };
316
183
 
317
- function getCardinality(collection) {
318
- const collectionLen = Array.isArray(collection) ? collection.length : undefined;
184
+ ParallelLoopCharacteristics.prototype._onCompleteMessage = function onCompleteMessage(_, message) {
185
+ const chr = this.characteristics;
186
+ const {
187
+ content
188
+ } = message;
189
+ if (content.output !== undefined) chr.output[content.index] = content.output;
190
+ this.running--;
191
+ this.activity.broker.publish('execution', 'execute.iteration.completed', { ...content,
192
+ ...chr.getContent(),
193
+ index: this.index,
194
+ running: this.running,
195
+ output: chr.output,
196
+ state: 'iteration.completed',
197
+ preventComplete: true
198
+ });
199
+
200
+ if (this.running <= 0 && !chr.next(this.index)) {
201
+ return chr.complete(content);
202
+ }
319
203
 
320
- if (!loopCardinality) {
321
- return collectionLen;
322
- }
204
+ if (chr.isCompletionConditionMet(message)) {
205
+ return chr.complete(content);
206
+ }
323
207
 
324
- const value = environment.resolveExpression(loopCardinality, executeMessage);
325
- if (value === undefined) return collectionLen;
326
- return Number(value);
327
- }
208
+ if (this.running <= 0) {
209
+ this.running = 0;
328
210
 
329
- function getCollection() {
330
- if (!collectionExpression) return;
331
- debug(`<${id}> has collection`);
332
- return environment.resolveExpression(collectionExpression, executeMessage);
333
- }
211
+ this._startBatch();
212
+ }
213
+ };
214
+
215
+ function Characteristics(activity, loopCharacteristics, executeMessage) {
216
+ this.activity = activity;
217
+ const behaviour = this.behaviour = loopCharacteristics.behaviour || {};
218
+ this.message = executeMessage;
219
+ const type = this.type = loopCharacteristics.type || 'LoopCharacteristics';
220
+ this.id = activity.id;
221
+ this.broker = activity.broker;
222
+ this.parentExecutionId = executeMessage.content.executionId;
223
+ this.isSequential = behaviour.isSequential || false;
224
+ this.output = executeMessage.content.output || [];
225
+ this.parent = (0, _messageHelper.unshiftParent)(executeMessage.content.parent, executeMessage.content);
226
+ if ('loopCardinality' in behaviour) this.loopCardinality = behaviour.loopCardinality;else if ('loopMaximum' in behaviour) this.loopCardinality = behaviour.loopMaximum;
334
227
 
335
- function subscribe(onIterationCompleteMessage) {
336
- broker.subscribeTmp('api', `activity.*.${parentExecutionId}`, onApiMessage, {
337
- noAck: true,
338
- consumerTag: apiConsumerTag
339
- }, {
340
- priority: 400
341
- });
342
- broker.subscribeTmp('execution', 'execute.*', onComplete, {
343
- noAck: true,
344
- consumerTag: executeConsumerTag,
345
- priority: 300
346
- });
347
-
348
- function onComplete(routingKey, message, ...args) {
349
- if (!message.content.isMultiInstance) return;
350
-
351
- switch (routingKey) {
352
- case 'execute.cancel':
353
- case 'execute.completed':
354
- return onIterationCompleteMessage(routingKey, message, ...args);
355
- }
356
- }
357
- }
228
+ if (behaviour.loopCondition) {
229
+ if (behaviour.testBefore) this.startCondition = behaviour.loopCondition;else this.completionCondition = behaviour.loopCondition;
358
230
  }
359
231
 
360
- function onApiMessage(_, message) {
361
- switch (message.properties.type) {
362
- case 'stop':
363
- case 'discard':
364
- stop();
365
- break;
366
- }
232
+ if (behaviour.completionCondition) {
233
+ this.completionCondition = behaviour.completionCondition;
234
+ }
235
+
236
+ const collection = this.collection = this.getCollection();
237
+
238
+ if (collection) {
239
+ this.elementVariable = behaviour.elementVariable || 'item';
240
+ }
241
+
242
+ this.cardinality = this.getCardinality(collection);
243
+ this.onApiMessage = this.onApiMessage.bind(this);
244
+ const environment = activity.environment;
245
+ this.logger = environment.Logger(type.toLowerCase());
246
+ this.batchSize = environment.settings.batchSize || 50;
247
+ }
248
+
249
+ Characteristics.prototype.getContent = function getContent() {
250
+ return { ...(0, _messageHelper.cloneContent)(this.message.content),
251
+ loopCardinality: this.cardinality,
252
+ isSequential: this.isSequential,
253
+ output: undefined
254
+ };
255
+ };
256
+
257
+ Characteristics.prototype.next = function next(index) {
258
+ const cardinality = this.cardinality;
259
+ if (cardinality > 0 && index >= cardinality) return;
260
+ const collection = this.collection;
261
+ if (collection && index >= collection.length) return;
262
+ const content = { ...this.getContent(),
263
+ isRootScope: undefined,
264
+ executionId: `${this.parentExecutionId}_${index}`,
265
+ isMultiInstance: true,
266
+ parent: (0, _messageHelper.cloneParent)(this.parent),
267
+ index
268
+ };
269
+
270
+ if (collection) {
271
+ content[this.elementVariable] = collection[index];
272
+ }
273
+
274
+ return content;
275
+ };
276
+
277
+ Characteristics.prototype.getCardinality = function getCardinality(collection) {
278
+ const collectionLen = this.collection && Array.isArray(collection) ? collection.length : undefined;
279
+
280
+ if (!this.loopCardinality) {
281
+ return collectionLen;
367
282
  }
368
283
 
369
- function stop() {
370
- broker.cancel(executeConsumerTag);
371
- broker.cancel(apiConsumerTag);
284
+ const value = this.activity.environment.resolveExpression(this.loopCardinality, this.message);
285
+
286
+ if (value !== undefined && isNaN(value) || value < 0) {
287
+ throw new _Errors.RunError(`<${this.id}> invalid loop cardinality >${value}<`, this.message);
372
288
  }
373
289
 
374
- function isConditionMet(condition, message, loopOutput) {
375
- if (!condition) return false;
376
- const testContext = (0, _messageHelper.cloneMessage)(message, {
377
- loopOutput
378
- });
379
- return environment.resolveExpression(condition, testContext);
290
+ if (value === undefined) return collectionLen;
291
+ return Number(value);
292
+ };
293
+
294
+ Characteristics.prototype.getCollection = function getCollection() {
295
+ const collectionExpression = this.behaviour.collection;
296
+ if (!collectionExpression) return;
297
+ return this.activity.environment.resolveExpression(collectionExpression, this.message);
298
+ };
299
+
300
+ Characteristics.prototype.isStartConditionMet = function isStartConditionMet(message) {
301
+ if (!this.startCondition) return false;
302
+ return this.activity.environment.resolveExpression(this.startCondition, (0, _messageHelper.cloneMessage)(message));
303
+ };
304
+
305
+ Characteristics.prototype.isCompletionConditionMet = function isCompletionConditionMet(message) {
306
+ if (!this.completionCondition) return false;
307
+ return this.activity.environment.resolveExpression(this.completionCondition, (0, _messageHelper.cloneMessage)(message, {
308
+ loopOutput: this.output
309
+ }));
310
+ };
311
+
312
+ Characteristics.prototype.complete = function complete(content) {
313
+ this.stop();
314
+ return this.broker.publish('execution', 'execute.completed', { ...content,
315
+ ...this.getContent(),
316
+ output: this.output
317
+ });
318
+ };
319
+
320
+ Characteristics.prototype.subscribe = function subscribe(onIterationCompleteMessage) {
321
+ this.broker.subscribeTmp('api', `activity.*.${this.parentExecutionId}`, this.onApiMessage, {
322
+ noAck: true,
323
+ consumerTag: '_api-multi-instance-tag'
324
+ }, {
325
+ priority: 400
326
+ });
327
+ this.broker.subscribeTmp('execution', 'execute.*', onComplete, {
328
+ noAck: true,
329
+ consumerTag: '_execute-q-multi-instance-tag',
330
+ priority: 300
331
+ });
332
+
333
+ function onComplete(routingKey, message, ...args) {
334
+ if (!message.content.isMultiInstance) return;
335
+
336
+ switch (routingKey) {
337
+ case 'execute.cancel':
338
+ case 'execute.completed':
339
+ return onIterationCompleteMessage(routingKey, message, ...args);
340
+ }
341
+ }
342
+ };
343
+
344
+ Characteristics.prototype.onApiMessage = function onApiMessage(_, message) {
345
+ switch (message.properties.type) {
346
+ case 'stop':
347
+ case 'discard':
348
+ this.stop();
349
+ break;
380
350
  }
381
- }
351
+ };
352
+
353
+ Characteristics.prototype.stop = function stop() {
354
+ this.broker.cancel('_execute-q-multi-instance-tag');
355
+ this.broker.cancel('_api-multi-instance-tag');
356
+ };
357
+
358
+ Characteristics.prototype.debug = function debug(msg) {
359
+ this.logger.debug(`<${this.parentExecutionId} (${this.id})> ${msg}`);
360
+ };