bpmn-elements 17.3.0 → 18.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 (155) hide show
  1. package/README.md +3 -1
  2. package/dist/Api.js +83 -0
  3. package/dist/Context.js +228 -22
  4. package/dist/Environment.js +111 -31
  5. package/dist/EventBroker.js +57 -1
  6. package/dist/Expressions.js +3 -4
  7. package/dist/MessageFormatter.js +29 -16
  8. package/dist/Timers.js +13 -9
  9. package/dist/Tracker.js +1 -0
  10. package/dist/activity/Activity.js +434 -233
  11. package/dist/activity/ActivityExecution.js +113 -40
  12. package/dist/activity/Dummy.js +6 -1
  13. package/dist/activity/Escalation.js +36 -24
  14. package/dist/activity/ExecutionScope.js +1 -1
  15. package/dist/activity/Message.js +36 -24
  16. package/dist/activity/Signal.js +36 -24
  17. package/dist/activity/outbound-evaluator.js +1 -1
  18. package/dist/condition.js +12 -6
  19. package/dist/constants.js +27 -0
  20. package/dist/definition/Definition.js +187 -64
  21. package/dist/definition/DefinitionExecution.js +198 -84
  22. package/dist/error/BpmnError.js +12 -1
  23. package/dist/error/Errors.js +50 -9
  24. package/dist/eventDefinitions/CancelEventDefinition.js +29 -11
  25. package/dist/eventDefinitions/CompensateEventDefinition.js +51 -31
  26. package/dist/eventDefinitions/ConditionalEventDefinition.js +21 -9
  27. package/dist/eventDefinitions/ErrorEventDefinition.js +46 -30
  28. package/dist/eventDefinitions/EscalationEventDefinition.js +44 -27
  29. package/dist/eventDefinitions/EventDefinitionExecution.js +30 -23
  30. package/dist/eventDefinitions/LinkEventDefinition.js +45 -120
  31. package/dist/eventDefinitions/MessageEventDefinition.js +44 -29
  32. package/dist/eventDefinitions/SignalEventDefinition.js +46 -31
  33. package/dist/eventDefinitions/TerminateEventDefinition.js +10 -1
  34. package/dist/eventDefinitions/TimerEventDefinition.js +57 -37
  35. package/dist/eventDefinitions/index.js +20 -21
  36. package/dist/events/BoundaryEvent.js +52 -40
  37. package/dist/events/EndEvent.js +22 -8
  38. package/dist/events/IntermediateCatchEvent.js +26 -8
  39. package/dist/events/IntermediateThrowEvent.js +24 -9
  40. package/dist/events/StartEvent.js +30 -14
  41. package/dist/events/index.js +10 -11
  42. package/dist/flows/Association.js +50 -7
  43. package/dist/flows/MessageFlow.js +49 -10
  44. package/dist/flows/SequenceFlow.js +93 -22
  45. package/dist/flows/index.js +6 -7
  46. package/dist/gateways/EventBasedGateway.js +29 -15
  47. package/dist/gateways/ExclusiveGateway.js +20 -5
  48. package/dist/gateways/InclusiveGateway.js +21 -5
  49. package/dist/gateways/ParallelGateway.js +253 -15
  50. package/dist/gateways/index.js +8 -9
  51. package/dist/getPropertyValue.js +1 -1
  52. package/dist/index.js +42 -43
  53. package/dist/io/BpmnIO.js +15 -1
  54. package/dist/io/EnvironmentDataObject.js +29 -1
  55. package/dist/io/EnvironmentDataStore.js +24 -1
  56. package/dist/io/EnvironmentDataStoreReference.js +24 -1
  57. package/dist/io/InputOutputSpecification.js +21 -11
  58. package/dist/io/Properties.js +28 -17
  59. package/dist/messageHelper.js +41 -4
  60. package/dist/process/Lane.js +15 -4
  61. package/dist/process/Process.js +176 -77
  62. package/dist/process/ProcessExecution.js +397 -178
  63. package/dist/shared.js +2 -0
  64. package/dist/tasks/CallActivity.js +19 -4
  65. package/dist/tasks/LoopCharacteristics.js +94 -9
  66. package/dist/tasks/ReceiveTask.js +36 -21
  67. package/dist/tasks/ScriptTask.js +22 -6
  68. package/dist/tasks/ServiceImplementation.js +7 -4
  69. package/dist/tasks/ServiceTask.js +19 -4
  70. package/dist/tasks/SignalTask.js +19 -4
  71. package/dist/tasks/StandardLoopCharacteristics.js +8 -4
  72. package/dist/tasks/SubProcess.js +44 -29
  73. package/dist/tasks/Task.js +19 -4
  74. package/dist/tasks/Transaction.js +8 -4
  75. package/dist/tasks/index.js +16 -18
  76. package/package.json +31 -13
  77. package/src/Api.js +70 -0
  78. package/src/Context.js +200 -19
  79. package/src/Environment.js +99 -30
  80. package/src/EventBroker.js +46 -1
  81. package/src/Expressions.js +2 -3
  82. package/src/MessageFormatter.js +24 -16
  83. package/src/Timers.js +12 -9
  84. package/src/Tracker.js +1 -0
  85. package/src/activity/Activity.js +372 -218
  86. package/src/activity/ActivityExecution.js +93 -42
  87. package/src/activity/Dummy.js +6 -1
  88. package/src/activity/Escalation.js +25 -18
  89. package/src/activity/ExecutionScope.js +1 -1
  90. package/src/activity/Message.js +25 -18
  91. package/src/activity/Signal.js +25 -18
  92. package/src/activity/outbound-evaluator.js +1 -1
  93. package/src/condition.js +11 -5
  94. package/src/constants.js +21 -0
  95. package/src/definition/Definition.js +165 -63
  96. package/src/definition/DefinitionExecution.js +164 -85
  97. package/src/error/BpmnError.js +11 -1
  98. package/src/error/Errors.js +44 -5
  99. package/src/eventDefinitions/CancelEventDefinition.js +27 -13
  100. package/src/eventDefinitions/CompensateEventDefinition.js +48 -32
  101. package/src/eventDefinitions/ConditionalEventDefinition.js +20 -10
  102. package/src/eventDefinitions/ErrorEventDefinition.js +44 -33
  103. package/src/eventDefinitions/EscalationEventDefinition.js +39 -26
  104. package/src/eventDefinitions/EventDefinitionExecution.js +30 -24
  105. package/src/eventDefinitions/LinkEventDefinition.js +34 -120
  106. package/src/eventDefinitions/MessageEventDefinition.js +42 -31
  107. package/src/eventDefinitions/SignalEventDefinition.js +43 -32
  108. package/src/eventDefinitions/TerminateEventDefinition.js +9 -1
  109. package/src/eventDefinitions/TimerEventDefinition.js +53 -35
  110. package/src/eventDefinitions/index.js +10 -23
  111. package/src/events/BoundaryEvent.js +50 -39
  112. package/src/events/EndEvent.js +19 -7
  113. package/src/events/IntermediateCatchEvent.js +24 -8
  114. package/src/events/IntermediateThrowEvent.js +24 -8
  115. package/src/events/StartEvent.js +25 -14
  116. package/src/events/index.js +5 -18
  117. package/src/flows/Association.js +43 -9
  118. package/src/flows/MessageFlow.js +41 -10
  119. package/src/flows/SequenceFlow.js +82 -19
  120. package/src/flows/index.js +3 -4
  121. package/src/gateways/EventBasedGateway.js +27 -15
  122. package/src/gateways/ExclusiveGateway.js +16 -3
  123. package/src/gateways/InclusiveGateway.js +16 -3
  124. package/src/gateways/ParallelGateway.js +301 -10
  125. package/src/gateways/index.js +4 -4
  126. package/src/getPropertyValue.js +1 -1
  127. package/src/index.js +19 -19
  128. package/src/io/BpmnIO.js +13 -1
  129. package/src/io/EnvironmentDataObject.js +26 -1
  130. package/src/io/EnvironmentDataStore.js +22 -1
  131. package/src/io/EnvironmentDataStoreReference.js +22 -1
  132. package/src/io/InputOutputSpecification.js +17 -8
  133. package/src/io/Properties.js +23 -13
  134. package/src/messageHelper.js +36 -4
  135. package/src/process/Lane.js +14 -4
  136. package/src/process/Process.js +157 -74
  137. package/src/process/ProcessExecution.js +363 -176
  138. package/src/shared.js +1 -0
  139. package/src/tasks/CallActivity.js +16 -2
  140. package/src/tasks/LoopCharacteristics.js +77 -11
  141. package/src/tasks/ReceiveTask.js +33 -22
  142. package/src/tasks/ScriptTask.js +17 -3
  143. package/src/tasks/ServiceImplementation.js +6 -3
  144. package/src/tasks/ServiceTask.js +16 -2
  145. package/src/tasks/SignalTask.js +16 -2
  146. package/src/tasks/StandardLoopCharacteristics.js +7 -3
  147. package/src/tasks/SubProcess.js +37 -23
  148. package/src/tasks/Task.js +16 -2
  149. package/src/tasks/Transaction.js +7 -3
  150. package/src/tasks/index.js +8 -9
  151. package/types/bundle-errors.d.ts +1 -0
  152. package/types/bundle.d.ts +97 -0
  153. package/types/index.d.ts +2619 -84
  154. package/types/interfaces.d.ts +638 -0
  155. package/types/types.d.ts +0 -765
@@ -1,4 +1,4 @@
1
- import ActivityExecution from './ActivityExecution.js';
1
+ import { ActivityExecution } from './ActivityExecution.js';
2
2
  import { getUniqueId } from '../shared.js';
3
3
  import { ActivityApi } from '../Api.js';
4
4
  import { ActivityBroker } from '../EventBroker.js';
@@ -6,39 +6,55 @@ import { Formatter } from '../MessageFormatter.js';
6
6
  import { cloneContent, cloneParent, cloneMessage } from '../messageHelper.js';
7
7
  import { makeErrorFromMessage, ActivityError } from '../error/Errors.js';
8
8
  import { OutboundEvaluator, formatFlowAction } from './outbound-evaluator.js';
9
-
10
- const kActivityDef = Symbol.for('activityDefinition');
11
- const kConsuming = Symbol.for('consuming');
12
- const kConsumingRunQ = Symbol.for('run queue consumer');
13
- const kCounters = Symbol.for('counters');
14
- const kEventDefinitions = Symbol.for('eventDefinitions');
15
- const kExec = Symbol.for('exec');
16
- const kExecuteMessage = Symbol.for('executeMessage');
17
- const kExtensions = Symbol.for('extensions');
18
- const kFlags = Symbol.for('flags');
19
- const kFlows = Symbol.for('flows');
20
- const kFormatter = Symbol.for('formatter');
21
- const kMessageHandlers = Symbol.for('messageHandlers');
22
- const kStateMessage = Symbol.for('stateMessage');
23
- const kActivated = Symbol.for('activated');
24
-
25
- export default Activity;
26
-
27
- function Activity(Behaviour, activityDef, context) {
9
+ import {
10
+ K_ACTIVATED,
11
+ K_CONSUMING,
12
+ K_COUNTERS,
13
+ K_EXECUTE_MESSAGE,
14
+ K_EXTENSIONS,
15
+ K_MESSAGE_HANDLERS,
16
+ K_STATE_MESSAGE,
17
+ } from '../constants.js';
18
+
19
+ const K_ACTIVITY_DEF = Symbol.for('activityDefinition');
20
+ const K_CONSUMING_RUN_Q = Symbol.for('run queue consumer');
21
+ const K_EVENT_DEFINITIONS = Symbol.for('eventDefinitions');
22
+ const K_EXEC = Symbol.for('exec');
23
+ const K_FLAGS = Symbol.for('flags');
24
+ const K_FLOWS = Symbol.for('flows');
25
+ const K_FORMATTER = Symbol.for('formatter');
26
+
27
+ /**
28
+ * Activity wraps any element (task, event, gateway) and orchestrates its lifecycle through the broker.
29
+ * @param {import('#types').IActivityBehaviour} Behaviour Element-specific behaviour constructor invoked per execution
30
+ * @param {import('moddle-context-serializer').Activity} activityDef Parsed BPMN element definition
31
+ * @param {import('#types').ContextInstance} context Per-execution registry and factory
32
+ */
33
+ export function Activity(Behaviour, activityDef, context) {
28
34
  const { id, type = 'activity', name, behaviour = {} } = activityDef;
29
35
  const { attachedTo: attachedToRef, eventDefinitions } = behaviour;
30
36
 
31
- this[kActivityDef] = activityDef;
37
+ this[K_ACTIVITY_DEF] = activityDef;
32
38
  this.id = id;
33
39
  this.type = type;
34
40
  this.name = name;
35
- this.behaviour = { ...behaviour, eventDefinitions };
41
+ /** @type {import('moddle-context-serializer').ActivityBehaviour} */
42
+ this.behaviour = {
43
+ ...behaviour,
44
+ eventDefinitions,
45
+ ...(activityDef.linkNames && { linkNames: activityDef.linkNames, linkBehaviour: activityDef.linkBehaviour }),
46
+ };
36
47
  this.Behaviour = Behaviour;
48
+ /** @type {import('moddle-context-serializer').Parent} */
37
49
  this.parent = activityDef.parent ? cloneParent(activityDef.parent) : {};
50
+ /** @type {import('#types').ILogger} */
38
51
  this.logger = context.environment.Logger(type.toLowerCase());
39
52
  this.environment = context.environment;
40
53
  this.context = context;
41
- this[kCounters] = {
54
+ /** @type {import('#types').ActivityStatus | undefined} */
55
+ this.status = undefined;
56
+
57
+ this[K_COUNTERS] = {
42
58
  taken: 0,
43
59
  discarded: 0,
44
60
  };
@@ -60,159 +76,175 @@ function Activity(Behaviour, activityDef, context) {
60
76
 
61
77
  const inboundSequenceFlows = context.getInboundSequenceFlows(id);
62
78
  const inboundAssociations = context.getInboundAssociations(id);
63
- let inboundTriggers;
64
- if (attachedToActivity) {
65
- inboundTriggers = [attachedToActivity];
66
- } else if (isForCompensation) {
67
- inboundTriggers = inboundAssociations.slice();
68
- } else {
69
- inboundTriggers = inboundSequenceFlows.slice();
70
- }
79
+ const hasInboundTrigger = attachedToActivity ? true : isForCompensation ? !!inboundAssociations.length : !!inboundSequenceFlows.length;
80
+
71
81
  const outboundSequenceFlows = context.getOutboundSequenceFlows(id);
72
82
 
73
- const isParallelJoin = activityDef.isParallelGateway && inboundSequenceFlows.length > 1;
83
+ const inboundSourceIds = new Set(inboundSequenceFlows.map(({ sourceId }) => sourceId));
84
+ const isParallelJoin = activityDef.isParallelGateway && inboundSourceIds.size > 1;
74
85
 
75
- this[kFlows] = {
86
+ this[K_FLOWS] = {
76
87
  inboundSequenceFlows,
77
88
  inboundAssociations,
78
- inboundTriggers,
89
+ inboundTriggers: undefined,
79
90
  outboundSequenceFlows,
80
91
  outboundEvaluator: new OutboundEvaluator(this, outboundSequenceFlows),
81
- ...(isParallelJoin && {
82
- inboundJoinFlows: new Set(),
83
- inboundSourceIds: new Set(inboundSequenceFlows.map(({ sourceId }) => sourceId)),
84
- }),
85
92
  };
86
93
 
87
- this[kFlags] = {
94
+ this[K_FLAGS] = {
88
95
  isEnd: !outboundSequenceFlows.length,
89
- isStart: !inboundTriggers.length && !behaviour.triggeredByEvent,
96
+ isStart: !hasInboundTrigger && !behaviour.triggeredByEvent && !activityDef.isCatching,
90
97
  isSubProcess: activityDef.isSubProcess,
91
98
  isMultiInstance: !!behaviour.loopCharacteristics,
92
99
  isForCompensation,
93
100
  attachedTo,
94
101
  isTransaction: activityDef.isTransaction,
95
102
  isParallelJoin,
103
+ isParallelGateway: activityDef.isParallelGateway,
104
+ isStartEvent: !!activityDef.isStartEvent,
96
105
  isThrowing: activityDef.isThrowing,
106
+ linkNames: activityDef.linkNames,
107
+ linkBehaviour: activityDef.linkBehaviour,
108
+ isCatching: activityDef.isCatching,
97
109
  lane: activityDef.lane?.id,
98
110
  };
99
- this[kExec] = new Map();
111
+ this[K_EXEC] = new Map();
100
112
 
101
- this[kMessageHandlers] = {
102
- onInbound: isParallelJoin ? this._onJoinInbound.bind(this) : this._onInbound.bind(this),
113
+ this[K_MESSAGE_HANDLERS] = {
114
+ onInbound: this._onInbound.bind(this),
103
115
  onRunMessage: this._onRunMessage.bind(this),
104
116
  onApiMessage: this._onApiMessage.bind(this),
105
117
  onExecutionMessage: this._onExecutionMessage.bind(this),
106
118
  };
107
119
 
108
- this[kEventDefinitions] = eventDefinitions?.map((ed, idx) => new ed.Behaviour(this, ed, context, idx));
109
- this[kExtensions] = context.loadExtensions(this);
110
- this[kConsuming] = false;
111
- this[kConsumingRunQ] = undefined;
120
+ /** @type {import('#types').EventDefinition[] | undefined} */
121
+ this[K_EVENT_DEFINITIONS] = eventDefinitions?.map((ed, idx) => new ed.Behaviour(this, ed, context, idx));
122
+ this[K_EXTENSIONS] = context.loadExtensions(this);
123
+ this[K_CONSUMING] = false;
124
+ this[K_CONSUMING_RUN_Q] = undefined;
112
125
  }
113
126
 
114
127
  Object.defineProperties(Activity.prototype, {
115
128
  counters: {
116
129
  get() {
117
- return { ...this[kCounters] };
130
+ return { ...this[K_COUNTERS] };
118
131
  },
119
132
  },
120
133
  execution: {
121
134
  get() {
122
- return this[kExec].get('execution');
135
+ return this[K_EXEC].get('execution');
123
136
  },
124
137
  },
125
138
  executionId: {
126
139
  get() {
127
- return this[kExec].get('executionId');
140
+ return this[K_EXEC].get('executionId');
128
141
  },
129
142
  },
130
143
  extensions: {
131
144
  get() {
132
- return this[kExtensions];
145
+ return this[K_EXTENSIONS];
133
146
  },
134
147
  },
135
148
  bpmnIo: {
136
149
  get() {
137
- const extensions = this[kExtensions];
150
+ const extensions = this[K_EXTENSIONS];
138
151
  return extensions?.extensions.find((e) => e.type === 'bpmnio');
139
152
  },
140
153
  },
141
154
  formatter: {
142
155
  get() {
143
- let formatter = this[kFormatter];
156
+ let formatter = this[K_FORMATTER];
144
157
  if (formatter) return formatter;
145
-
146
- formatter = this[kFormatter] = new Formatter(this);
158
+ formatter = this[K_FORMATTER] = new Formatter(this);
147
159
  return formatter;
148
160
  },
149
161
  },
150
162
  isRunning: {
151
163
  get() {
152
- if (!this[kConsuming]) return false;
164
+ if (!this[K_CONSUMING]) return false;
153
165
  return !!this.status;
154
166
  },
155
167
  },
156
168
  outbound: {
157
169
  get() {
158
- return this[kFlows].outboundSequenceFlows;
170
+ return this[K_FLOWS].outboundSequenceFlows;
159
171
  },
160
172
  },
161
173
  inbound: {
162
174
  get() {
163
- return this[kFlows].inboundSequenceFlows;
175
+ return this[K_FLOWS].inboundSequenceFlows;
164
176
  },
165
177
  },
166
178
  isEnd: {
167
179
  get() {
168
- return this[kFlags].isEnd;
180
+ return this[K_FLAGS].isEnd;
169
181
  },
170
182
  },
171
183
  isStart: {
172
184
  get() {
173
- return this[kFlags].isStart;
185
+ return this[K_FLAGS].isStart;
174
186
  },
175
187
  },
176
188
  isSubProcess: {
177
189
  get() {
178
- return this[kFlags].isSubProcess;
190
+ return this[K_FLAGS].isSubProcess;
179
191
  },
180
192
  },
181
193
  isTransaction: {
182
194
  get() {
183
- return this[kFlags].isTransaction;
195
+ return this[K_FLAGS].isTransaction;
184
196
  },
185
197
  },
186
198
  isMultiInstance: {
187
199
  get() {
188
- return this[kFlags].isMultiInstance;
200
+ return this[K_FLAGS].isMultiInstance;
189
201
  },
190
202
  },
191
203
  isThrowing: {
192
204
  get() {
193
- return this[kFlags].isThrowing;
205
+ return this[K_FLAGS].isThrowing;
206
+ },
207
+ },
208
+ isCatching: {
209
+ get() {
210
+ return this[K_FLAGS].isCatching;
194
211
  },
195
212
  },
196
213
  isForCompensation: {
197
214
  get() {
198
- return this[kFlags].isForCompensation;
215
+ return this[K_FLAGS].isForCompensation;
216
+ },
217
+ },
218
+ isParallelJoin: {
219
+ get() {
220
+ return this[K_FLAGS].isParallelJoin;
221
+ },
222
+ },
223
+ isParallelGateway: {
224
+ get() {
225
+ return this[K_FLAGS].isParallelGateway;
226
+ },
227
+ },
228
+ isStartEvent: {
229
+ get() {
230
+ return this[K_FLAGS].isStartEvent;
199
231
  },
200
232
  },
201
233
  triggeredByEvent: {
202
234
  get() {
203
- return this[kActivityDef].triggeredByEvent;
235
+ return this[K_ACTIVITY_DEF].triggeredByEvent;
204
236
  },
205
237
  },
206
238
  attachedTo: {
207
239
  get() {
208
- const attachedToId = this[kFlags].attachedTo;
240
+ const attachedToId = this[K_FLAGS].attachedTo;
209
241
  if (!attachedToId) return null;
210
242
  return this.getActivityById(attachedToId);
211
243
  },
212
244
  },
213
245
  lane: {
214
246
  get() {
215
- const laneId = this[kFlags].lane;
247
+ const laneId = this[K_FLAGS].lane;
216
248
  if (!laneId) return undefined;
217
249
  const parent = this.parentElement;
218
250
  return parent.getLaneById && parent.getLaneById(laneId);
@@ -220,7 +252,7 @@ Object.defineProperties(Activity.prototype, {
220
252
  },
221
253
  eventDefinitions: {
222
254
  get() {
223
- return this[kEventDefinitions];
255
+ return this[K_EVENT_DEFINITIONS];
224
256
  },
225
257
  },
226
258
  parentElement: {
@@ -228,36 +260,85 @@ Object.defineProperties(Activity.prototype, {
228
260
  return this.context.getActivityParentById(this.id);
229
261
  },
230
262
  },
263
+ initialized: {
264
+ get() {
265
+ return !!this[K_EXEC]?.get('initExecutionId');
266
+ },
267
+ },
231
268
  });
232
269
 
270
+ /**
271
+ * Subscribe to inbound flows and start consuming the inbound queue.
272
+ * @returns {void}
273
+ */
233
274
  Activity.prototype.activate = function activate() {
234
- if (this[kActivated]) return;
235
- this[kActivated] = true;
275
+ if (this[K_ACTIVATED]) return;
276
+ this[K_ACTIVATED] = true;
236
277
  return this.addInboundListeners() && this._consumeInbound();
237
278
  };
238
279
 
280
+ /** @internal */
281
+ Activity.prototype._getInboundTriggers = function _getInboundTriggers() {
282
+ const flows = this[K_FLOWS];
283
+ if (flows.inboundTriggers) return flows.inboundTriggers;
284
+
285
+ const flags = this[K_FLAGS];
286
+ let triggers;
287
+ if (flags.attachedTo) {
288
+ triggers = [this.context.getActivityById(flags.attachedTo)];
289
+ } else if (flags.isForCompensation) {
290
+ triggers = flows.inboundAssociations.slice();
291
+ } else {
292
+ triggers = flows.inboundSequenceFlows.slice();
293
+ }
294
+
295
+ const { isCatching, linkNames, linkBehaviour } = flags;
296
+ if (isCatching && linkNames?.length) {
297
+ const known = new Set(triggers.map((t) => t.id));
298
+ for (const source of this.context.getActivitiesByEventDefinitionBehaviour(linkBehaviour, linkNames)) {
299
+ if (source.id === this.id || !source.isThrowing || known.has(source.id)) continue;
300
+ triggers.push(source);
301
+ known.add(source.id);
302
+ }
303
+ }
304
+
305
+ return (flows.inboundTriggers = triggers);
306
+ };
307
+
308
+ /**
309
+ * Cancel inbound subscriptions and any pending run/format consumers.
310
+ */
239
311
  Activity.prototype.deactivate = function deactivate() {
240
- this[kActivated] = false;
312
+ this[K_ACTIVATED] = false;
241
313
  const broker = this.broker;
242
314
  this.removeInboundListeners();
243
315
  broker.cancel('_run-on-inbound');
244
316
  broker.cancel('_format-consumer');
245
317
  };
246
318
 
319
+ /**
320
+ * Initialise activity executionId and emit init event without starting the run.
321
+ * @param {Record<string, any>} [initContent] Optional content merged into the init message
322
+ */
247
323
  Activity.prototype.init = function init(initContent) {
248
324
  const id = this.id;
249
- const exec = this[kExec];
325
+ const exec = this[K_EXEC];
250
326
  const executionId = exec.has('initExecutionId') ? exec.get('initExecutionId') : getUniqueId(id);
251
327
  exec.set('initExecutionId', executionId);
252
328
  this.logger.debug(`<${id}> initialized with executionId <${executionId}>`);
253
329
  this._publishEvent('init', this._createMessage({ ...initContent, executionId }));
254
330
  };
255
331
 
332
+ /**
333
+ * Start running the activity by publishing run.enter and run.start.
334
+ * @param {Record<string, any>} [runContent] Optional content merged into the run message
335
+ * @throws {Error} if the activity is already running
336
+ */
256
337
  Activity.prototype.run = function run(runContent) {
257
338
  const id = this.id;
258
339
  if (this.isRunning) throw new Error(`activity <${id}> is already running`);
259
340
 
260
- const exec = this[kExec];
341
+ const exec = this[K_EXEC];
261
342
  const executionId = exec.get('initExecutionId') || getUniqueId(id);
262
343
  exec.set('executionId', executionId);
263
344
  exec.delete('initExecutionId');
@@ -270,13 +351,18 @@ Activity.prototype.run = function run(runContent) {
270
351
  broker.publish('run', 'run.enter', content);
271
352
  broker.publish('run', 'run.start', cloneContent(content));
272
353
 
273
- this[kConsuming] = true;
354
+ this[K_CONSUMING] = true;
274
355
  this._consumeRunQ();
275
356
  };
276
357
 
358
+ /**
359
+ * Snapshot activity state for recover.
360
+ * Returns undefined when nothing is running and `disableTrackState` is set.
361
+ * @returns {import('#types').ActivityState}
362
+ */
277
363
  Activity.prototype.getState = function getState() {
278
364
  const status = this.status;
279
- const exec = this[kExec];
365
+ const exec = this[K_EXEC];
280
366
  const execution = exec.get('execution');
281
367
  const executionId = exec.get('executionId');
282
368
  const brokerState = this.broker.getState(true);
@@ -294,16 +380,22 @@ Activity.prototype.getState = function getState() {
294
380
  };
295
381
  };
296
382
 
383
+ /**
384
+ * Restore activity state captured by getState. Cannot be called while running.
385
+ * @param {import('#types').ActivityState} [state]
386
+ * @returns {this} this when state was applied
387
+ * @throws {Error} when activity is currently running
388
+ */
297
389
  Activity.prototype.recover = function recover(state) {
298
390
  if (this.isRunning) throw new Error(`cannot recover running activity <${this.id}>`);
299
- if (!state) return;
391
+ if (!state) return this;
300
392
 
301
393
  this.stopped = state.stopped;
302
394
  this.status = state.status;
303
- const exec = this[kExec];
395
+ const exec = this[K_EXEC];
304
396
  exec.set('executionId', state.executionId);
305
397
 
306
- this[kCounters] = { ...this[kCounters], ...state.counters };
398
+ this[K_COUNTERS] = { ...this[K_COUNTERS], ...state.counters };
307
399
 
308
400
  if (state.execution) {
309
401
  exec.set('execution', new ActivityExecution(this, this.context).recover(state.execution));
@@ -314,8 +406,12 @@ Activity.prototype.recover = function recover(state) {
314
406
  return this;
315
407
  };
316
408
 
409
+ /**
410
+ * Resume after recover. If no run has been started, falls back to activate.
411
+ * @throws {Error} when called on a running activity
412
+ */
317
413
  Activity.prototype.resume = function resume() {
318
- if (this[kConsuming]) {
414
+ if (this[K_CONSUMING]) {
319
415
  throw new Error(`cannot resume running activity <${this.id}>`);
320
416
  }
321
417
  if (!this.status) return this.activate();
@@ -327,25 +423,34 @@ Activity.prototype.resume = function resume() {
327
423
  const content = this._createMessage();
328
424
  this.broker.publish('run', 'run.resume', content, { persistent: false });
329
425
 
330
- this[kConsuming] = true;
426
+ this[K_CONSUMING] = true;
331
427
  this._consumeRunQ();
332
428
  };
333
429
 
430
+ /**
431
+ * Discard the activity. Stops execution if running; the activity leaves without taking any outbound flow.
432
+ * @param {Record<string, any>} [discardContent] Optional content propagated with the discard
433
+ * @returns {void}
434
+ */
334
435
  Activity.prototype.discard = function discard(discardContent) {
335
436
  if (!this.status) return this._runDiscard(discardContent);
336
- const execution = this[kExec].get('execution');
437
+ const execution = this[K_EXEC].get('execution');
337
438
  if (execution && !execution.completed) return execution.discard();
338
439
 
339
440
  this._deactivateRunConsumers();
340
441
  const broker = this.broker;
341
442
  broker.getQueue('run-q').purge();
342
- broker.publish('run', 'run.discard', cloneContent(this[kStateMessage].content));
343
- this[kConsuming] = true;
443
+ broker.publish('run', 'run.discard', cloneContent(this[K_STATE_MESSAGE].content));
444
+ this[K_CONSUMING] = true;
344
445
  this._consumeRunQ();
345
446
  };
346
447
 
448
+ /**
449
+ * Subscribe to inbound triggers (sequence flows, attached activity, or compensation associations).
450
+ * @returns {number} count of subscribed triggers
451
+ */
347
452
  Activity.prototype.addInboundListeners = function addInboundListeners() {
348
- const triggers = this[kFlows].inboundTriggers;
453
+ const triggers = this._getInboundTriggers();
349
454
  if (triggers.length) {
350
455
  const onInboundEvent = this._onInboundEvent.bind(this);
351
456
  const triggerConsumerTag = `_inbound-${this.id}`;
@@ -362,21 +467,33 @@ Activity.prototype.addInboundListeners = function addInboundListeners() {
362
467
  return triggers.length;
363
468
  };
364
469
 
470
+ /**
471
+ * Cancel inbound trigger subscriptions added by addInboundListeners.
472
+ */
365
473
  Activity.prototype.removeInboundListeners = function removeInboundListeners() {
474
+ const triggers = this[K_FLOWS].inboundTriggers;
475
+ if (!triggers) return;
366
476
  const triggerConsumerTag = `_inbound-${this.id}`;
367
- for (const trigger of this[kFlows].inboundTriggers) {
477
+ for (const trigger of triggers) {
368
478
  trigger.broker.cancel(triggerConsumerTag);
369
479
  }
370
480
  };
371
481
 
482
+ /**
483
+ * Stop the activity. If not currently running, just cancels the inbound consumer.
484
+ */
372
485
  Activity.prototype.stop = function stop() {
373
- if (!this[kConsuming]) return this.broker.cancel('_run-on-inbound');
374
- return this.getApi(this[kStateMessage]).stop();
486
+ if (!this[K_CONSUMING]) return this.broker.cancel('_run-on-inbound');
487
+ return this.getApi(this[K_STATE_MESSAGE]).stop();
375
488
  };
376
489
 
490
+ /**
491
+ * Advance one run-step when the environment runs in step mode. No-op otherwise.
492
+ */
377
493
  Activity.prototype.next = function next() {
378
494
  if (!this.environment.settings.step) return;
379
- const stateMessage = this[kStateMessage];
495
+ /** @type {import('#types').ElementBrokerMessage} */
496
+ const stateMessage = this[K_STATE_MESSAGE];
380
497
  if (!stateMessage) return;
381
498
  if (this.status === 'executing') return false;
382
499
  if (this.status === 'formatting') return false;
@@ -385,26 +502,46 @@ Activity.prototype.next = function next() {
385
502
  return current;
386
503
  };
387
504
 
505
+ /**
506
+ * Walk outbound flows to discover the activity graph from this point.
507
+ */
388
508
  Activity.prototype.shake = function shake() {
389
509
  this._shakeOutbound({ content: this._createMessage() });
390
510
  };
391
511
 
512
+ /**
513
+ * Evaluate outbound sequence flows for the given source message.
514
+ * @param {import('#types').ElementBrokerMessage} fromMessage Source run message
515
+ * @param {boolean} discardRestAtTake When true, take only the first matching flow and discard the rest
516
+ * @param {(err: Error, evaluationResult: any) => void} callback
517
+ * @returns {void}
518
+ */
392
519
  Activity.prototype.evaluateOutbound = function evaluateOutbound(fromMessage, discardRestAtTake, callback) {
393
- return this[kFlows].outboundEvaluator.evaluate(fromMessage, discardRestAtTake, callback);
520
+ return this[K_FLOWS].outboundEvaluator.evaluate(fromMessage, discardRestAtTake, callback);
394
521
  };
395
522
 
523
+ /**
524
+ * Resolve an Api wrapper for the activity, preferring the running execution if any.
525
+ * @param {import('#types').ElementBrokerMessage} [message]
526
+ * @returns {import('#types').IApi<import('./Activity.js').Activity>}
527
+ */
396
528
  Activity.prototype.getApi = function getApi(message) {
397
- const execution = this[kExec].get('execution');
529
+ const execution = this[K_EXEC].get('execution');
398
530
  if (execution && !execution.completed) return execution.getApi(message);
399
- return ActivityApi(this.broker, message || this[kStateMessage]);
531
+ return ActivityApi(this.broker, message || this[K_STATE_MESSAGE]);
400
532
  };
401
533
 
534
+ /**
535
+ * Look up another activity in the same context.
536
+ * @param {string} elementId
537
+ */
402
538
  Activity.prototype.getActivityById = function getActivityById(elementId) {
403
539
  return this.context.getActivityById(elementId);
404
540
  };
405
541
 
542
+ /** @internal */
406
543
  Activity.prototype._runDiscard = function runDiscard(discardContent) {
407
- const exec = this[kExec];
544
+ const exec = this[K_EXEC];
408
545
  const executionId = exec.get('initExecutionId') || getUniqueId(this.id);
409
546
  exec.set('executionId', executionId);
410
547
  exec.delete('initExecutionId');
@@ -414,15 +551,16 @@ Activity.prototype._runDiscard = function runDiscard(discardContent) {
414
551
  const content = this._createMessage({ ...discardContent, executionId });
415
552
  this.broker.publish('run', 'run.discard', content);
416
553
 
417
- this[kConsuming] = true;
554
+ this[K_CONSUMING] = true;
418
555
  this._consumeRunQ();
419
556
  };
420
557
 
558
+ /** @internal */
421
559
  Activity.prototype._discardRun = function discardRun() {
422
560
  const status = this.status;
423
561
  if (!status) return;
424
562
 
425
- const execution = this[kExec].get('execution');
563
+ const execution = this[K_EXEC].get('execution');
426
564
  if (execution && !execution.completed) return;
427
565
 
428
566
  let discardRoutingKey = 'run.discard';
@@ -440,47 +578,82 @@ Activity.prototype._discardRun = function discardRun() {
440
578
 
441
579
  this._deactivateRunConsumers();
442
580
 
443
- const stateMessage = this[kStateMessage];
581
+ const stateMessage = this[K_STATE_MESSAGE];
444
582
  if (this.extensions) this.extensions.deactivate(cloneMessage(stateMessage));
445
583
 
446
584
  const broker = this.broker;
447
585
  broker.getQueue('run-q').purge();
448
586
 
449
587
  broker.publish('run', discardRoutingKey, cloneContent(stateMessage.content), { correlationId: stateMessage.properties.correlationId });
450
- this[kConsuming] = true;
588
+ this[K_CONSUMING] = true;
451
589
  this._consumeRunQ();
452
590
  };
453
591
 
592
+ /** @internal */
593
+ Activity.prototype._onShakeMessage = function _onShakeMessage(sourceMessage) {
594
+ if (this[K_FLAGS].isParallelGateway) {
595
+ const message = cloneMessage(sourceMessage, { join: this.id });
596
+ message.content.sequence.push({ id: this.id, type: this.type });
597
+ return this.broker.publish('event', 'activity.shake.join', message.content, {
598
+ persistent: false,
599
+ type: 'shake',
600
+ });
601
+ }
602
+
603
+ this._shakeOutbound(sourceMessage);
604
+ };
605
+
606
+ /** @internal */
454
607
  Activity.prototype._shakeOutbound = function shakeOutbound(sourceMessage) {
455
608
  const message = cloneMessage(sourceMessage);
456
- message.content.sequence = message.content.sequence || [];
457
- message.content.sequence.push({ id: this.id, type: this.type });
609
+ const sequence = (message.content.sequence = message.content.sequence || []);
610
+ const count = 1;
611
+ const looped = sequence?.find((f) => f.id === this.id);
612
+
613
+ sequence.push({ id: this.id, type: this.type, count: looped ? looped.count + 1 : count });
458
614
 
459
- const broker = this.broker;
460
615
  this.broker.publish('api', 'activity.shake.start', message.content, { persistent: false, type: 'shake' });
461
616
 
462
- if (this[kFlags].isEnd) {
463
- return broker.publish('event', 'activity.shake.end', message.content, { persistent: false, type: 'shake' });
617
+ const flags = this[K_FLAGS];
618
+ if (flags.isThrowing && flags.linkNames?.length) {
619
+ for (const target of this.context.getActivitiesByEventDefinitionBehaviour(flags.linkBehaviour, flags.linkNames)) {
620
+ if (target.id === this.id || !target.isCatching) continue;
621
+ const linkedContent = cloneContent(message.content, { sourceId: this.id, targetId: target.id, isLinked: true });
622
+ linkedContent.sequence = linkedContent.sequence.concat({ id: target.id, type: target.type });
623
+ target.broker.publish('event', 'activity.shake.linked', linkedContent, { persistent: false, type: 'shake' });
624
+ for (const flow of target.outbound) flow.shake({ content: cloneContent(linkedContent) });
625
+ }
626
+ }
627
+
628
+ if (this[K_FLAGS].isEnd) {
629
+ return this.broker.publish('event', 'activity.shake.end', cloneContent(message.content), { persistent: false, type: 'shake' });
630
+ }
631
+
632
+ const targets = new Map();
633
+
634
+ for (const outboundFlow of this[K_FLOWS].outboundSequenceFlows) {
635
+ const prevTarget = targets.get(outboundFlow.targetId);
636
+ if (!prevTarget) {
637
+ targets.set(outboundFlow.targetId, outboundFlow);
638
+ }
464
639
  }
465
640
 
466
- for (const flow of this[kFlows].outboundSequenceFlows) flow.shake(message);
641
+ for (const t of targets.values()) t.shake(message);
467
642
  };
468
643
 
644
+ /** @internal */
469
645
  Activity.prototype._consumeInbound = function consumeInbound() {
470
- if (!this[kActivated]) return;
646
+ if (!this[K_ACTIVATED]) return;
471
647
 
472
- if (this.status || !this[kFlows].inboundTriggers.length) return;
648
+ if (this.status || !this._getInboundTriggers().length) return;
473
649
 
474
650
  const inboundQ = this.broker.getQueue('inbound-q');
475
- const onInbound = this[kMessageHandlers].onInbound;
476
-
477
- if (this[kFlags].isParallelJoin) {
478
- return inboundQ.assertConsumer(onInbound, { consumerTag: '_run-on-inbound', prefetch: 1000 });
479
- }
651
+ const onInbound = this[K_MESSAGE_HANDLERS].onInbound;
480
652
 
481
653
  return inboundQ.assertConsumer(onInbound, { consumerTag: '_run-on-inbound' });
482
654
  };
483
655
 
656
+ /** @internal */
484
657
  Activity.prototype._onInbound = function onInbound(routingKey, message) {
485
658
  message.ack();
486
659
  const broker = this.broker;
@@ -490,6 +663,12 @@ Activity.prototype._onInbound = function onInbound(routingKey, message) {
490
663
  const inbound = [cloneContent(content)];
491
664
 
492
665
  switch (routingKey) {
666
+ case 'activity.relink':
667
+ if (content.executionId) this[K_EXEC].set('initExecutionId', content.executionId);
668
+ return this.run({
669
+ message: content.message,
670
+ inbound,
671
+ });
493
672
  case 'association.take':
494
673
  case 'flow.take':
495
674
  case 'activity.restart':
@@ -498,64 +677,13 @@ Activity.prototype._onInbound = function onInbound(routingKey, message) {
498
677
  message: content.message,
499
678
  inbound,
500
679
  });
501
- case 'flow.discard':
502
680
  case 'activity.discard': {
503
- let discardSequence;
504
- if (content.discardSequence) discardSequence = content.discardSequence.slice();
505
- return this._runDiscard({ inbound, discardSequence });
506
- }
507
- }
508
- };
509
-
510
- Activity.prototype._onJoinInbound = function onJoinInbound(routingKey, message) {
511
- const { content } = message;
512
- const { inboundJoinFlows, inboundSourceIds } = this[kFlows];
513
- let alreadyTouched = false;
514
-
515
- const touched = new Set();
516
-
517
- let taken;
518
- for (const msg of inboundJoinFlows) {
519
- const sourceId = msg.content.sourceId;
520
- touched.add(sourceId);
521
- if (sourceId === content.sourceId) {
522
- alreadyTouched = true;
523
- }
524
- }
525
-
526
- inboundJoinFlows.add(message);
527
-
528
- if (alreadyTouched) return;
529
-
530
- const remaining = inboundSourceIds.size - touched.size - 1;
531
- if (remaining) {
532
- return this.logger.debug(`<${this.id}> inbound ${message.content.action} from <${message.content.id}>, ${remaining} remaining`);
533
- }
534
-
535
- const inbound = [];
536
- for (const im of inboundJoinFlows) {
537
- if (im.fields.routingKey === 'flow.take') taken = true;
538
- im.ack();
539
- inbound.push(cloneContent(im.content));
540
- }
541
-
542
- const discardSequence = new Set();
543
- if (!taken) {
544
- for (const im of inboundJoinFlows) {
545
- if (!im.content.discardSequence) continue;
546
- for (const sourceId of im.content.discardSequence) {
547
- discardSequence.add(sourceId);
548
- }
681
+ return this._runDiscard({ inbound });
549
682
  }
550
683
  }
551
-
552
- inboundJoinFlows.clear();
553
- this.broker.cancel('_run-on-inbound');
554
-
555
- if (!taken) return this._runDiscard({ inbound, discardSequence: [...discardSequence] });
556
- return this.run({ inbound });
557
684
  };
558
685
 
686
+ /** @internal */
559
687
  Activity.prototype._onInboundEvent = function onInboundEvent(routingKey, message) {
560
688
  const { fields, content, properties } = message;
561
689
  const inboundQ = this.broker.getQueue('inbound-q');
@@ -563,36 +691,54 @@ Activity.prototype._onInboundEvent = function onInboundEvent(routingKey, message
563
691
  switch (routingKey) {
564
692
  case 'activity.enter':
565
693
  case 'activity.discard': {
566
- if (content.id === this[kFlags].attachedTo) {
694
+ if (content.id === this[K_FLAGS].attachedTo) {
567
695
  inboundQ.queueMessage(fields, cloneContent(content), properties);
568
696
  }
569
697
  break;
570
698
  }
571
- case 'flow.shake': {
572
- return this._shakeOutbound(message);
699
+ case 'flow.shake':
700
+ case 'activity.shake.start':
701
+ return this._onShakeMessage(message);
702
+ case 'activity.link': {
703
+ const linkName = content.message?.linkName;
704
+ if (!this[K_FLAGS].linkNames?.includes(linkName)) break;
705
+ const executionId = getUniqueId(this.id);
706
+ this.broker.publish(
707
+ 'event',
708
+ 'activity.enter',
709
+ cloneContent(content, { id: this.id, type: this.type, executionId, state: 'enter', message: { ...content.message } })
710
+ );
711
+ inboundQ.queueMessage(
712
+ { routingKey: 'activity.relink' },
713
+ cloneContent(content, { id: this.id, executionId, message: { ...content.message } }),
714
+ properties
715
+ );
716
+ return;
573
717
  }
574
718
  case 'association.take':
575
719
  case 'flow.take':
576
- case 'flow.discard':
577
720
  return inboundQ.queueMessage(fields, cloneContent(content), properties);
578
721
  }
579
722
  };
580
723
 
724
+ /** @internal */
581
725
  Activity.prototype._consumeRunQ = function consumeRunQ() {
582
- this[kConsumingRunQ] = true;
583
- this.broker.getQueue('run-q').assertConsumer(this[kMessageHandlers].onRunMessage, { exclusive: true, consumerTag: '_activity-run' });
726
+ this[K_CONSUMING_RUN_Q] = true;
727
+ this.broker.getQueue('run-q').assertConsumer(this[K_MESSAGE_HANDLERS].onRunMessage, { exclusive: true, consumerTag: '_activity-run' });
584
728
  };
585
729
 
730
+ /** @internal */
586
731
  Activity.prototype._pauseRunQ = function pauseRunQ() {
587
- if (!this[kConsumingRunQ]) return;
732
+ if (!this[K_CONSUMING_RUN_Q]) return;
588
733
 
589
- this[kConsumingRunQ] = false;
734
+ this[K_CONSUMING_RUN_Q] = false;
590
735
  this.broker.cancel('_activity-run');
591
736
  };
592
737
 
738
+ /** @internal */
593
739
  Activity.prototype._onRunMessage = function onRunMessage(routingKey, message, messageProperties) {
594
740
  switch (routingKey) {
595
- case 'run.outbound.discard':
741
+ case 'run.execute.passthrough':
596
742
  case 'run.outbound.take':
597
743
  case 'run.next':
598
744
  return this._continueRunMessage(routingKey, message, messageProperties);
@@ -614,6 +760,7 @@ Activity.prototype._onRunMessage = function onRunMessage(routingKey, message, me
614
760
  });
615
761
  };
616
762
 
763
+ /** @internal */
617
764
  Activity.prototype._continueRunMessage = function continueRunMessage(routingKey, message) {
618
765
  const isRedelivered = message.fields.redelivered;
619
766
  const content = cloneContent(message.content);
@@ -621,7 +768,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
621
768
 
622
769
  const id = this.id;
623
770
  const step = this.environment.settings.step;
624
- this[kStateMessage] = message;
771
+ this[K_STATE_MESSAGE] = message;
625
772
 
626
773
  switch (routingKey) {
627
774
  case 'run.enter': {
@@ -629,7 +776,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
629
776
 
630
777
  this.status = 'entered';
631
778
  if (!isRedelivered) {
632
- this[kExec].delete('execution');
779
+ this[K_EXEC].delete('execution');
633
780
  if (this.extensions) this.extensions.activate(cloneMessage(message));
634
781
  this._publishEvent('enter', content, { correlationId });
635
782
  }
@@ -639,7 +786,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
639
786
  this.logger.debug(`<${id}> discard`, isRedelivered ? 'redelivered' : '');
640
787
 
641
788
  this.status = 'discard';
642
- this[kExec].delete('execution');
789
+ this[K_EXEC].delete('execution');
643
790
 
644
791
  if (this.extensions) this.extensions.activate(cloneMessage(message));
645
792
 
@@ -659,20 +806,20 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
659
806
  break;
660
807
  }
661
808
  case 'run.execute.passthrough': {
662
- const execution = this[kExec].get('execution');
809
+ const execution = this[K_EXEC].get('execution');
663
810
  if (!isRedelivered && execution) {
664
811
  if (execution.completed) return message.ack();
665
- this[kExecuteMessage] = message;
812
+ this[K_EXECUTE_MESSAGE] = message;
666
813
  return execution.passthrough(message);
667
814
  }
668
815
  }
669
816
  case 'run.execute': {
670
817
  this.status = 'executing';
671
- this[kExecuteMessage] = message;
818
+ this[K_EXECUTE_MESSAGE] = message;
672
819
 
673
820
  if (isRedelivered && this.extensions) this.extensions.activate(cloneMessage(message));
674
821
 
675
- const exec = this[kExec];
822
+ const exec = this[K_EXEC];
676
823
  let execution = exec.get('execution');
677
824
  if (!execution) {
678
825
  execution = new ActivityExecution(this, this.context);
@@ -681,14 +828,14 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
681
828
 
682
829
  this.broker
683
830
  .getQueue('execution-q')
684
- .assertConsumer(this[kMessageHandlers].onExecutionMessage, { exclusive: true, consumerTag: '_activity-execution' });
831
+ .assertConsumer(this[K_MESSAGE_HANDLERS].onExecutionMessage, { exclusive: true, consumerTag: '_activity-execution' });
685
832
  return execution.execute(message);
686
833
  }
687
834
  case 'run.end': {
688
835
  this.logger.debug(`<${id}> end`, isRedelivered ? 'redelivered' : '');
689
836
  if (isRedelivered) break;
690
837
 
691
- this[kCounters].taken++;
838
+ this[K_COUNTERS].taken++;
692
839
 
693
840
  this.status = 'end';
694
841
 
@@ -710,7 +857,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
710
857
  }
711
858
  case 'run.discarded': {
712
859
  this.logger.debug(`<${content.executionId} (${id})> discarded`);
713
- this[kCounters].discarded++;
860
+ this[K_COUNTERS].discarded++;
714
861
 
715
862
  this.status = 'discarded';
716
863
  content.outbound = undefined;
@@ -728,11 +875,6 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
728
875
  message.ack();
729
876
  return flow.take(content.flow);
730
877
  }
731
- case 'run.outbound.discard': {
732
- const flow = this._getOutboundSequenceFlowById(content.flow.id);
733
- message.ack();
734
- return flow.discard(content.flow);
735
- }
736
878
  case 'run.leave': {
737
879
  this.status = undefined;
738
880
 
@@ -754,8 +896,9 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
754
896
  if (!step) message.ack();
755
897
  };
756
898
 
899
+ /** @internal */
757
900
  Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey, message) {
758
- const executeMessage = this[kExecuteMessage];
901
+ const executeMessage = this[K_EXECUTE_MESSAGE];
759
902
  const content = cloneContent({
760
903
  ...executeMessage.content,
761
904
  ...message.content,
@@ -770,7 +913,7 @@ Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey,
770
913
 
771
914
  switch (routingKey) {
772
915
  case 'execution.outbound.take': {
773
- return this._doOutbound(message, false, (err, outbound) => {
916
+ return this._doOutbound(message, (err, outbound) => {
774
917
  message.ack();
775
918
  if (err) return this.emitFatal(err, content);
776
919
  broker.publish('run', 'run.execute.passthrough', cloneContent(content, { outbound }));
@@ -784,10 +927,11 @@ Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey,
784
927
  break;
785
928
  }
786
929
  case 'execution.cancel':
787
- case 'execution.discard':
930
+ case 'execution.discard': {
788
931
  this.status = 'discarded';
789
932
  broker.publish('run', 'run.discarded', content, { correlationId });
790
933
  break;
934
+ }
791
935
  default: {
792
936
  this.status = 'executed';
793
937
  broker.publish('run', 'run.end', content, { correlationId });
@@ -798,21 +942,23 @@ Activity.prototype._onExecutionMessage = function onExecutionMessage(routingKey,
798
942
  this._ackRunExecuteMessage();
799
943
  };
800
944
 
945
+ /** @internal */
801
946
  Activity.prototype._ackRunExecuteMessage = function ackRunExecuteMessage() {
802
947
  if (this.environment.settings.step) return;
803
- const executeMessage = this[kExecuteMessage];
948
+ const executeMessage = this[K_EXECUTE_MESSAGE];
804
949
  executeMessage.ack();
805
950
  };
806
951
 
952
+ /** @internal */
807
953
  Activity.prototype._doRunLeave = function doRunLeave(message, isDiscarded, onOutbound) {
808
954
  const { content, properties } = message;
809
955
  const correlationId = properties.correlationId;
810
- if (content.ignoreOutbound) {
956
+ if (isDiscarded || content.ignoreOutbound) {
811
957
  this.broker.publish('run', 'run.leave', cloneContent(content), { correlationId });
812
958
  return onOutbound();
813
959
  }
814
960
 
815
- return this._doOutbound(cloneMessage(message), isDiscarded, (err, outbound) => {
961
+ return this._doOutbound(cloneMessage(message), (err, outbound) => {
816
962
  if (err) {
817
963
  return this._publishEvent('error', { ...content, error: err }, { correlationId });
818
964
  }
@@ -830,39 +976,34 @@ Activity.prototype._doRunLeave = function doRunLeave(message, isDiscarded, onOut
830
976
  });
831
977
  };
832
978
 
833
- Activity.prototype._doOutbound = function doOutbound(fromMessage, isDiscarded, callback) {
834
- const outboundSequenceFlows = this[kFlows].outboundSequenceFlows;
979
+ /** @internal */
980
+ Activity.prototype._doOutbound = function doOutbound(fromMessage, callback) {
981
+ const outboundSequenceFlows = this[K_FLOWS].outboundSequenceFlows;
835
982
  if (!outboundSequenceFlows.length) return callback(null, []);
836
983
 
837
984
  const fromContent = fromMessage.content;
838
985
 
839
- let discardSequence = fromContent.discardSequence;
840
- if (isDiscarded && !discardSequence && this[kFlags].attachedTo && fromContent.inbound?.[0]) {
841
- discardSequence = [fromContent.inbound[0].id];
842
- }
843
-
844
986
  let outboundFlows;
845
- if (isDiscarded) {
846
- outboundFlows = outboundSequenceFlows.map((flow) => formatFlowAction(flow, { action: 'discard' }));
847
- } else if (fromContent.outbound?.length) {
987
+ if (fromContent.outbound?.length) {
848
988
  outboundFlows = outboundSequenceFlows.map((flow) => formatFlowAction(flow, fromContent.outbound.filter((f) => f.id === flow.id).pop()));
849
989
  }
850
990
 
851
991
  if (outboundFlows) {
852
- this._doRunOutbound(outboundFlows, fromContent, discardSequence);
992
+ this._doRunOutbound(outboundFlows, fromContent);
853
993
  return callback(null, outboundFlows);
854
994
  }
855
995
 
856
996
  return this.evaluateOutbound(fromMessage, fromContent.outboundTakeOne, (err, evaluatedOutbound) => {
857
997
  if (err) return callback(new ActivityError(err.message, fromMessage, err));
858
- const outbound = this._doRunOutbound(evaluatedOutbound, fromContent, discardSequence);
998
+ const outbound = this._doRunOutbound(evaluatedOutbound, fromContent);
859
999
  return callback(null, outbound);
860
1000
  });
861
1001
  };
862
1002
 
863
- Activity.prototype._doRunOutbound = function doRunOutbound(outboundList, content, discardSequence) {
1003
+ /** @internal */
1004
+ Activity.prototype._doRunOutbound = function doRunOutbound(outboundList, content) {
864
1005
  if (outboundList.length === 1) {
865
- this._publishRunOutbound(outboundList[0], content, discardSequence);
1006
+ this._publishRunOutbound(outboundList[0], content);
866
1007
  } else {
867
1008
  const targets = new Map();
868
1009
 
@@ -876,15 +1017,21 @@ Activity.prototype._doRunOutbound = function doRunOutbound(outboundList, content
876
1017
  }
877
1018
 
878
1019
  for (const outboundFlow of targets.values()) {
879
- this._publishRunOutbound(outboundFlow, content, discardSequence);
1020
+ this._publishRunOutbound(outboundFlow, content);
880
1021
  }
881
1022
  }
882
1023
 
883
1024
  return outboundList;
884
1025
  };
885
1026
 
886
- Activity.prototype._publishRunOutbound = function publishRunOutbound(outboundFlow, content, discardSequence) {
1027
+ /** @internal */
1028
+ Activity.prototype._publishRunOutbound = function publishRunOutbound(outboundFlow, content) {
887
1029
  const { id: flowId, action, result } = outboundFlow;
1030
+
1031
+ if (action === 'discard') {
1032
+ return;
1033
+ }
1034
+
888
1035
  this.broker.publish(
889
1036
  'run',
890
1037
  'run.outbound.' + action,
@@ -893,16 +1040,16 @@ Activity.prototype._publishRunOutbound = function publishRunOutbound(outboundFlo
893
1040
  ...(result && typeof result === 'object' && result),
894
1041
  ...outboundFlow,
895
1042
  sequenceId: getUniqueId(`${flowId}_${action}`),
896
- ...(discardSequence && { discardSequence: discardSequence.slice() }),
897
1043
  },
898
1044
  })
899
1045
  );
900
1046
  };
901
1047
 
1048
+ /** @internal */
902
1049
  Activity.prototype._onResumeMessage = function onResumeMessage(message) {
903
1050
  message.ack();
904
1051
 
905
- const stateMessage = this[kStateMessage];
1052
+ const stateMessage = this[K_STATE_MESSAGE];
906
1053
  const fields = stateMessage.fields;
907
1054
  if (!fields.redelivered) return;
908
1055
 
@@ -924,6 +1071,7 @@ Activity.prototype._onResumeMessage = function onResumeMessage(message) {
924
1071
  return this.broker.publish('run', fields.routingKey, cloneContent(stateMessage.content), stateMessage.properties);
925
1072
  };
926
1073
 
1074
+ /** @internal */
927
1075
  Activity.prototype._publishEvent = function publishEvent(state, content, properties) {
928
1076
  this.broker.publish('event', `activity.${state}`, cloneContent(content, { state }), {
929
1077
  ...properties,
@@ -932,12 +1080,13 @@ Activity.prototype._publishEvent = function publishEvent(state, content, propert
932
1080
  });
933
1081
  };
934
1082
 
1083
+ /** @internal */
935
1084
  Activity.prototype._onStop = function onStop(message) {
936
- const running = this[kConsuming];
1085
+ const running = this[K_CONSUMING];
937
1086
 
938
1087
  this.stopped = true;
939
1088
 
940
- this[kConsuming] = false;
1089
+ this[K_CONSUMING] = false;
941
1090
  const broker = this.broker;
942
1091
  this._pauseRunQ();
943
1092
  broker.cancel('_activity-api');
@@ -952,18 +1101,20 @@ Activity.prototype._onStop = function onStop(message) {
952
1101
  }
953
1102
  };
954
1103
 
1104
+ /** @internal */
955
1105
  Activity.prototype._consumeApi = function consumeApi() {
956
- const executionId = this[kExec].get('executionId');
1106
+ const executionId = this[K_EXEC].get('executionId');
957
1107
  if (!executionId) return;
958
1108
  const broker = this.broker;
959
1109
  broker.cancel('_activity-api');
960
- broker.subscribeTmp('api', `activity.*.${executionId}`, this[kMessageHandlers].onApiMessage, {
1110
+ broker.subscribeTmp('api', `activity.*.${executionId}`, this[K_MESSAGE_HANDLERS].onApiMessage, {
961
1111
  noAck: true,
962
1112
  consumerTag: '_activity-api',
963
1113
  priority: 100,
964
1114
  });
965
1115
  };
966
1116
 
1117
+ /** @internal */
967
1118
  Activity.prototype._onApiMessage = function onApiMessage(routingKey, message) {
968
1119
  switch (message.properties.type) {
969
1120
  case 'discard': {
@@ -978,6 +1129,7 @@ Activity.prototype._onApiMessage = function onApiMessage(routingKey, message) {
978
1129
  }
979
1130
  };
980
1131
 
1132
+ /** @internal */
981
1133
  Activity.prototype._createMessage = function createMessage(override) {
982
1134
  const { name, status, parent } = this;
983
1135
 
@@ -990,21 +1142,23 @@ Activity.prototype._createMessage = function createMessage(override) {
990
1142
  ...(parent && { parent: cloneParent(parent) }),
991
1143
  };
992
1144
 
993
- for (const [flag, value] of Object.entries(this[kFlags])) {
1145
+ for (const [flag, value] of Object.entries(this[K_FLAGS])) {
994
1146
  if (value) result[flag] = value;
995
1147
  }
996
1148
 
997
1149
  return result;
998
1150
  };
999
1151
 
1152
+ /** @internal */
1000
1153
  Activity.prototype._getOutboundSequenceFlowById = function getOutboundSequenceFlowById(flowId) {
1001
- return this[kFlows].outboundSequenceFlows.find((flow) => flow.id === flowId);
1154
+ return this[K_FLOWS].outboundSequenceFlows.find((flow) => flow.id === flowId);
1002
1155
  };
1003
1156
 
1157
+ /** @internal */
1004
1158
  Activity.prototype._deactivateRunConsumers = function _deactivateRunConsumers() {
1005
1159
  const broker = this.broker;
1006
1160
  broker.cancel('_activity-api');
1007
1161
  this._pauseRunQ();
1008
1162
  broker.cancel('_activity-execution');
1009
- this[kConsuming] = false;
1163
+ this[K_CONSUMING] = false;
1010
1164
  };