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.
- package/README.md +3 -1
- package/dist/Api.js +83 -0
- package/dist/Context.js +228 -22
- package/dist/Environment.js +111 -31
- package/dist/EventBroker.js +57 -1
- package/dist/Expressions.js +3 -4
- package/dist/MessageFormatter.js +29 -16
- package/dist/Timers.js +13 -9
- package/dist/Tracker.js +1 -0
- package/dist/activity/Activity.js +434 -233
- package/dist/activity/ActivityExecution.js +113 -40
- package/dist/activity/Dummy.js +6 -1
- package/dist/activity/Escalation.js +36 -24
- package/dist/activity/ExecutionScope.js +1 -1
- package/dist/activity/Message.js +36 -24
- package/dist/activity/Signal.js +36 -24
- package/dist/activity/outbound-evaluator.js +1 -1
- package/dist/condition.js +12 -6
- package/dist/constants.js +27 -0
- package/dist/definition/Definition.js +187 -64
- package/dist/definition/DefinitionExecution.js +198 -84
- package/dist/error/BpmnError.js +12 -1
- package/dist/error/Errors.js +50 -9
- package/dist/eventDefinitions/CancelEventDefinition.js +29 -11
- package/dist/eventDefinitions/CompensateEventDefinition.js +51 -31
- package/dist/eventDefinitions/ConditionalEventDefinition.js +21 -9
- package/dist/eventDefinitions/ErrorEventDefinition.js +46 -30
- package/dist/eventDefinitions/EscalationEventDefinition.js +44 -27
- package/dist/eventDefinitions/EventDefinitionExecution.js +30 -23
- package/dist/eventDefinitions/LinkEventDefinition.js +45 -120
- package/dist/eventDefinitions/MessageEventDefinition.js +44 -29
- package/dist/eventDefinitions/SignalEventDefinition.js +46 -31
- package/dist/eventDefinitions/TerminateEventDefinition.js +10 -1
- package/dist/eventDefinitions/TimerEventDefinition.js +57 -37
- package/dist/eventDefinitions/index.js +20 -21
- package/dist/events/BoundaryEvent.js +52 -40
- package/dist/events/EndEvent.js +22 -8
- package/dist/events/IntermediateCatchEvent.js +26 -8
- package/dist/events/IntermediateThrowEvent.js +24 -9
- package/dist/events/StartEvent.js +30 -14
- package/dist/events/index.js +10 -11
- package/dist/flows/Association.js +50 -7
- package/dist/flows/MessageFlow.js +49 -10
- package/dist/flows/SequenceFlow.js +93 -22
- package/dist/flows/index.js +6 -7
- package/dist/gateways/EventBasedGateway.js +29 -15
- package/dist/gateways/ExclusiveGateway.js +20 -5
- package/dist/gateways/InclusiveGateway.js +21 -5
- package/dist/gateways/ParallelGateway.js +253 -15
- package/dist/gateways/index.js +8 -9
- package/dist/getPropertyValue.js +1 -1
- package/dist/index.js +42 -43
- package/dist/io/BpmnIO.js +15 -1
- package/dist/io/EnvironmentDataObject.js +29 -1
- package/dist/io/EnvironmentDataStore.js +24 -1
- package/dist/io/EnvironmentDataStoreReference.js +24 -1
- package/dist/io/InputOutputSpecification.js +21 -11
- package/dist/io/Properties.js +28 -17
- package/dist/messageHelper.js +41 -4
- package/dist/process/Lane.js +15 -4
- package/dist/process/Process.js +176 -77
- package/dist/process/ProcessExecution.js +397 -178
- package/dist/shared.js +2 -0
- package/dist/tasks/CallActivity.js +19 -4
- package/dist/tasks/LoopCharacteristics.js +94 -9
- package/dist/tasks/ReceiveTask.js +36 -21
- package/dist/tasks/ScriptTask.js +22 -6
- package/dist/tasks/ServiceImplementation.js +7 -4
- package/dist/tasks/ServiceTask.js +19 -4
- package/dist/tasks/SignalTask.js +19 -4
- package/dist/tasks/StandardLoopCharacteristics.js +8 -4
- package/dist/tasks/SubProcess.js +44 -29
- package/dist/tasks/Task.js +19 -4
- package/dist/tasks/Transaction.js +8 -4
- package/dist/tasks/index.js +16 -18
- package/package.json +31 -13
- package/src/Api.js +70 -0
- package/src/Context.js +200 -19
- package/src/Environment.js +99 -30
- package/src/EventBroker.js +46 -1
- package/src/Expressions.js +2 -3
- package/src/MessageFormatter.js +24 -16
- package/src/Timers.js +12 -9
- package/src/Tracker.js +1 -0
- package/src/activity/Activity.js +372 -218
- package/src/activity/ActivityExecution.js +93 -42
- package/src/activity/Dummy.js +6 -1
- package/src/activity/Escalation.js +25 -18
- package/src/activity/ExecutionScope.js +1 -1
- package/src/activity/Message.js +25 -18
- package/src/activity/Signal.js +25 -18
- package/src/activity/outbound-evaluator.js +1 -1
- package/src/condition.js +11 -5
- package/src/constants.js +21 -0
- package/src/definition/Definition.js +165 -63
- package/src/definition/DefinitionExecution.js +164 -85
- package/src/error/BpmnError.js +11 -1
- package/src/error/Errors.js +44 -5
- package/src/eventDefinitions/CancelEventDefinition.js +27 -13
- package/src/eventDefinitions/CompensateEventDefinition.js +48 -32
- package/src/eventDefinitions/ConditionalEventDefinition.js +20 -10
- package/src/eventDefinitions/ErrorEventDefinition.js +44 -33
- package/src/eventDefinitions/EscalationEventDefinition.js +39 -26
- package/src/eventDefinitions/EventDefinitionExecution.js +30 -24
- package/src/eventDefinitions/LinkEventDefinition.js +34 -120
- package/src/eventDefinitions/MessageEventDefinition.js +42 -31
- package/src/eventDefinitions/SignalEventDefinition.js +43 -32
- package/src/eventDefinitions/TerminateEventDefinition.js +9 -1
- package/src/eventDefinitions/TimerEventDefinition.js +53 -35
- package/src/eventDefinitions/index.js +10 -23
- package/src/events/BoundaryEvent.js +50 -39
- package/src/events/EndEvent.js +19 -7
- package/src/events/IntermediateCatchEvent.js +24 -8
- package/src/events/IntermediateThrowEvent.js +24 -8
- package/src/events/StartEvent.js +25 -14
- package/src/events/index.js +5 -18
- package/src/flows/Association.js +43 -9
- package/src/flows/MessageFlow.js +41 -10
- package/src/flows/SequenceFlow.js +82 -19
- package/src/flows/index.js +3 -4
- package/src/gateways/EventBasedGateway.js +27 -15
- package/src/gateways/ExclusiveGateway.js +16 -3
- package/src/gateways/InclusiveGateway.js +16 -3
- package/src/gateways/ParallelGateway.js +301 -10
- package/src/gateways/index.js +4 -4
- package/src/getPropertyValue.js +1 -1
- package/src/index.js +19 -19
- package/src/io/BpmnIO.js +13 -1
- package/src/io/EnvironmentDataObject.js +26 -1
- package/src/io/EnvironmentDataStore.js +22 -1
- package/src/io/EnvironmentDataStoreReference.js +22 -1
- package/src/io/InputOutputSpecification.js +17 -8
- package/src/io/Properties.js +23 -13
- package/src/messageHelper.js +36 -4
- package/src/process/Lane.js +14 -4
- package/src/process/Process.js +157 -74
- package/src/process/ProcessExecution.js +363 -176
- package/src/shared.js +1 -0
- package/src/tasks/CallActivity.js +16 -2
- package/src/tasks/LoopCharacteristics.js +77 -11
- package/src/tasks/ReceiveTask.js +33 -22
- package/src/tasks/ScriptTask.js +17 -3
- package/src/tasks/ServiceImplementation.js +6 -3
- package/src/tasks/ServiceTask.js +16 -2
- package/src/tasks/SignalTask.js +16 -2
- package/src/tasks/StandardLoopCharacteristics.js +7 -3
- package/src/tasks/SubProcess.js +37 -23
- package/src/tasks/Task.js +16 -2
- package/src/tasks/Transaction.js +7 -3
- package/src/tasks/index.js +8 -9
- package/types/bundle-errors.d.ts +1 -0
- package/types/bundle.d.ts +97 -0
- package/types/index.d.ts +2619 -84
- package/types/interfaces.d.ts +638 -0
- package/types/types.d.ts +0 -765
|
@@ -2,24 +2,25 @@ import { ProcessApi } from '../Api.js';
|
|
|
2
2
|
import { cloneContent, cloneMessage, pushParent } from '../messageHelper.js';
|
|
3
3
|
import { getUniqueId } from '../shared.js';
|
|
4
4
|
import { ActivityTracker } from '../Tracker.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
import { K_ACTIVATED, K_COMPLETED, K_EXECUTE_MESSAGE, K_MESSAGE_HANDLERS, K_STATUS, K_STOPPED, STATE_VERSION } from '../constants.js';
|
|
6
|
+
|
|
7
|
+
const K_ACTIVITY_Q = Symbol.for('activityQ');
|
|
8
|
+
const K_ELEMENTS = Symbol.for('elements');
|
|
9
|
+
const K_PARENT = Symbol.for('parent');
|
|
10
|
+
const K_TRACKER = Symbol.for('activity tracker');
|
|
11
|
+
const K_PEERS_DISCOVERED = Symbol.for('peers discovered');
|
|
12
|
+
const K_RECOVERED_VERSION = Symbol.for('recovered version');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Drives the execution of a single process or sub-process: activates children, routes activity
|
|
16
|
+
* events, and rolls completion up to the owning Process or sub-process Activity.
|
|
17
|
+
* @param {import('#types').Process | import('#types').Activity} parentActivity
|
|
18
|
+
* @param {import('#types').ContextInstance} context
|
|
19
|
+
*/
|
|
20
|
+
export function ProcessExecution(parentActivity, context) {
|
|
20
21
|
const { id, type, broker, isSubProcess, isTransaction } = parentActivity;
|
|
21
22
|
|
|
22
|
-
this[
|
|
23
|
+
this[K_PARENT] = parentActivity;
|
|
23
24
|
this.id = id;
|
|
24
25
|
this.type = type;
|
|
25
26
|
this.isSubProcess = isSubProcess;
|
|
@@ -28,29 +29,30 @@ function ProcessExecution(parentActivity, context) {
|
|
|
28
29
|
this.environment = context.environment;
|
|
29
30
|
this.context = context;
|
|
30
31
|
|
|
31
|
-
this[
|
|
32
|
+
this[K_ELEMENTS] = {
|
|
32
33
|
postponed: new Set(),
|
|
33
34
|
children: context.getActivities(id),
|
|
34
35
|
associations: context.getAssociations(id),
|
|
35
36
|
flows: context.getSequenceFlows(id),
|
|
36
37
|
outboundMessageFlows: context.getMessageFlows(id),
|
|
37
38
|
startActivities: new Set(),
|
|
39
|
+
startEventCount: 0,
|
|
38
40
|
triggeredByEvent: new Set(),
|
|
39
41
|
detachedActivities: new Set(),
|
|
40
|
-
|
|
42
|
+
convergingGateways: new Set(),
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
const exchangeName = (this._exchangeName = isSubProcess ? 'subprocess-execution' : 'execution');
|
|
44
46
|
broker.assertExchange(exchangeName, 'topic', { autoDelete: false, durable: true });
|
|
45
47
|
|
|
46
|
-
this[
|
|
47
|
-
this[
|
|
48
|
-
this[
|
|
49
|
-
this[
|
|
50
|
-
this[
|
|
48
|
+
this[K_COMPLETED] = false;
|
|
49
|
+
this[K_STOPPED] = false;
|
|
50
|
+
this[K_ACTIVATED] = false;
|
|
51
|
+
this[K_STATUS] = 'init';
|
|
52
|
+
this[K_TRACKER] = new ActivityTracker(id);
|
|
51
53
|
this.executionId = undefined;
|
|
52
54
|
|
|
53
|
-
this[
|
|
55
|
+
this[K_MESSAGE_HANDLERS] = {
|
|
54
56
|
onActivityEvent: this._onActivityEvent.bind(this),
|
|
55
57
|
onApiMessage: this._onApiMessage.bind(this),
|
|
56
58
|
onChildMessage: this._onChildMessage.bind(this),
|
|
@@ -61,51 +63,56 @@ function ProcessExecution(parentActivity, context) {
|
|
|
61
63
|
Object.defineProperties(ProcessExecution.prototype, {
|
|
62
64
|
stopped: {
|
|
63
65
|
get() {
|
|
64
|
-
return this[
|
|
66
|
+
return this[K_STOPPED];
|
|
65
67
|
},
|
|
66
68
|
},
|
|
67
69
|
completed: {
|
|
68
70
|
get() {
|
|
69
|
-
return this[
|
|
71
|
+
return this[K_COMPLETED];
|
|
70
72
|
},
|
|
71
73
|
},
|
|
72
74
|
status: {
|
|
73
75
|
get() {
|
|
74
|
-
return this[
|
|
76
|
+
return this[K_STATUS];
|
|
75
77
|
},
|
|
76
78
|
},
|
|
77
79
|
postponedCount: {
|
|
78
80
|
get() {
|
|
79
|
-
return this[
|
|
81
|
+
return this[K_ELEMENTS].postponed.size;
|
|
80
82
|
},
|
|
81
83
|
},
|
|
82
84
|
isRunning: {
|
|
83
85
|
get() {
|
|
84
|
-
return this[
|
|
86
|
+
return this[K_ACTIVATED];
|
|
85
87
|
},
|
|
86
88
|
},
|
|
87
89
|
activityStatus: {
|
|
88
90
|
get() {
|
|
89
|
-
return this[
|
|
91
|
+
return this[K_TRACKER].activityStatus;
|
|
90
92
|
},
|
|
91
93
|
},
|
|
92
94
|
});
|
|
93
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Activate children and start the process execution. Resumes if the message is redelivered.
|
|
98
|
+
* @param {import('#types').ElementBrokerMessage} executeMessage
|
|
99
|
+
* @throws {Error} when message or executionId is missing
|
|
100
|
+
*/
|
|
94
101
|
ProcessExecution.prototype.execute = function execute(executeMessage) {
|
|
95
102
|
if (!executeMessage) throw new Error('Process execution requires message');
|
|
96
103
|
if (!executeMessage.content || !executeMessage.content.executionId) throw new Error('Process execution requires execution id');
|
|
97
104
|
|
|
98
105
|
const executionId = (this.executionId = executeMessage.content.executionId);
|
|
99
106
|
|
|
100
|
-
this[
|
|
107
|
+
this[K_EXECUTE_MESSAGE] = cloneMessage(executeMessage, {
|
|
101
108
|
executionId,
|
|
102
109
|
state: 'start',
|
|
103
110
|
});
|
|
104
111
|
|
|
105
|
-
this[
|
|
112
|
+
this[K_STOPPED] = false;
|
|
106
113
|
|
|
107
114
|
this.environment.assignVariables(executeMessage);
|
|
108
|
-
this[
|
|
115
|
+
this[K_ACTIVITY_Q] = this.broker.assertQueue(`execute-${executionId}-q`, { durable: true, autoDelete: false });
|
|
109
116
|
|
|
110
117
|
if (executeMessage.fields.redelivered) {
|
|
111
118
|
return this.resume();
|
|
@@ -117,33 +124,33 @@ ProcessExecution.prototype.execute = function execute(executeMessage) {
|
|
|
117
124
|
return true;
|
|
118
125
|
};
|
|
119
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Resume after recover, resuming any postponed children.
|
|
129
|
+
*/
|
|
120
130
|
ProcessExecution.prototype.resume = function resume() {
|
|
121
131
|
this._debug(`resume process execution at ${this.status}`);
|
|
122
132
|
|
|
123
|
-
if (this[
|
|
133
|
+
if (this[K_COMPLETED]) return this._complete('completed');
|
|
124
134
|
|
|
125
135
|
this._activate();
|
|
126
136
|
|
|
127
|
-
const {
|
|
128
|
-
|
|
129
|
-
if (startActivities.size > 1) {
|
|
130
|
-
for (const a of startActivities) a.shake();
|
|
131
|
-
}
|
|
137
|
+
const { postponed, detachedActivities } = this[K_ELEMENTS];
|
|
138
|
+
this._shakeOnStart();
|
|
132
139
|
|
|
133
140
|
postponed.clear();
|
|
134
141
|
detachedActivities.clear();
|
|
135
142
|
|
|
136
|
-
this[
|
|
143
|
+
this[K_ACTIVITY_Q].consume(this[K_MESSAGE_HANDLERS].onChildMessage, {
|
|
137
144
|
prefetch: 1000,
|
|
138
145
|
consumerTag: `_process-activity-${this.executionId}`,
|
|
139
146
|
});
|
|
140
147
|
|
|
141
|
-
if (this[
|
|
148
|
+
if (this[K_COMPLETED]) return;
|
|
142
149
|
|
|
143
150
|
const status = this.status;
|
|
144
151
|
if (status === 'init') return this._start();
|
|
145
152
|
|
|
146
|
-
const tracker = this[
|
|
153
|
+
const tracker = this[K_TRACKER];
|
|
147
154
|
for (const msg of new Set(postponed)) {
|
|
148
155
|
const activity = this.getActivityById(msg.content.id);
|
|
149
156
|
if (!activity) continue;
|
|
@@ -158,13 +165,21 @@ ProcessExecution.prototype.resume = function resume() {
|
|
|
158
165
|
activity.resume();
|
|
159
166
|
}
|
|
160
167
|
|
|
161
|
-
if (this[
|
|
168
|
+
if (this[K_COMPLETED]) return;
|
|
169
|
+
|
|
170
|
+
this._reconcileStartEvents();
|
|
171
|
+
|
|
172
|
+
if (this[K_COMPLETED]) return;
|
|
162
173
|
|
|
163
174
|
if (!postponed.size && status === 'executing') return this._complete('completed');
|
|
164
175
|
};
|
|
165
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Snapshot execution state including children, flows, message flows, and associations.
|
|
179
|
+
* @returns {import('#types').ProcessExecutionState}
|
|
180
|
+
*/
|
|
166
181
|
ProcessExecution.prototype.getState = function getState() {
|
|
167
|
-
const { children, flows, outboundMessageFlows, associations } = this[
|
|
182
|
+
const { children, flows, outboundMessageFlows, associations } = this[K_ELEMENTS];
|
|
168
183
|
|
|
169
184
|
const flowStates = flows.reduce((result, flow) => {
|
|
170
185
|
const elmState = flow.getState();
|
|
@@ -174,8 +189,8 @@ ProcessExecution.prototype.getState = function getState() {
|
|
|
174
189
|
|
|
175
190
|
return {
|
|
176
191
|
executionId: this.executionId,
|
|
177
|
-
stopped: this[
|
|
178
|
-
completed: this[
|
|
192
|
+
stopped: this[K_STOPPED],
|
|
193
|
+
completed: this[K_COMPLETED],
|
|
179
194
|
status: this.status,
|
|
180
195
|
children: children.reduce((result, activity) => {
|
|
181
196
|
if (activity.placeholder) return result;
|
|
@@ -191,13 +206,20 @@ ProcessExecution.prototype.getState = function getState() {
|
|
|
191
206
|
};
|
|
192
207
|
};
|
|
193
208
|
|
|
194
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Restore execution state captured by getState.
|
|
211
|
+
* @param {import('#types').ProcessExecutionState} [state]
|
|
212
|
+
* @param {number} [recoveredVersion] State version
|
|
213
|
+
* @returns {this}
|
|
214
|
+
*/
|
|
215
|
+
ProcessExecution.prototype.recover = function recover(state, recoveredVersion) {
|
|
195
216
|
if (!state) return this;
|
|
196
217
|
this.executionId = state.executionId;
|
|
218
|
+
this[K_RECOVERED_VERSION] = recoveredVersion;
|
|
197
219
|
|
|
198
|
-
this[
|
|
199
|
-
this[
|
|
200
|
-
this[
|
|
220
|
+
this[K_STOPPED] = state.stopped;
|
|
221
|
+
this[K_COMPLETED] = state.completed;
|
|
222
|
+
this[K_STATUS] = state.status;
|
|
201
223
|
|
|
202
224
|
this._debug(`recover process execution at ${this.status}`);
|
|
203
225
|
|
|
@@ -237,53 +259,29 @@ ProcessExecution.prototype.recover = function recover(state) {
|
|
|
237
259
|
return this;
|
|
238
260
|
};
|
|
239
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Walk activity graph from the given start id, or every start activity when omitted.
|
|
264
|
+
* @param {string} [fromId]
|
|
265
|
+
* @returns {import('#types').ShakeResult}
|
|
266
|
+
*/
|
|
240
267
|
ProcessExecution.prototype.shake = function shake(fromId) {
|
|
241
|
-
|
|
242
|
-
const id = this.id;
|
|
243
|
-
if (!this.isRunning) {
|
|
244
|
-
executing = false;
|
|
245
|
-
this.executionId = getUniqueId(id);
|
|
246
|
-
this._activate();
|
|
247
|
-
}
|
|
248
|
-
const toShake = fromId ? [this.getActivityById(fromId)].filter(Boolean) : this[kElements].startActivities;
|
|
249
|
-
|
|
250
|
-
const result = {};
|
|
251
|
-
this.broker.subscribeTmp(
|
|
252
|
-
'event',
|
|
253
|
-
'*.shake.*',
|
|
254
|
-
(routingKey, { content }) => {
|
|
255
|
-
let isLooped = false;
|
|
256
|
-
switch (routingKey) {
|
|
257
|
-
case 'flow.shake.loop':
|
|
258
|
-
isLooped = true;
|
|
259
|
-
case 'activity.shake.end': {
|
|
260
|
-
const { id: shakeId, parent: shakeParent } = content;
|
|
261
|
-
if (shakeParent.id !== id) return;
|
|
262
|
-
|
|
263
|
-
result[shakeId] = result[shakeId] || [];
|
|
264
|
-
result[shakeId].push({ ...content, isLooped });
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
},
|
|
269
|
-
{ noAck: true, consumerTag: `_shaker-${this.executionId}` }
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
for (const a of toShake) a.shake();
|
|
273
|
-
|
|
274
|
-
if (!executing) this._deactivate();
|
|
275
|
-
this.broker.cancel(`_shaker-${this.executionId}`);
|
|
276
|
-
|
|
277
|
-
return result;
|
|
268
|
+
return Object.fromEntries(this._shakeElements(fromId).sequences);
|
|
278
269
|
};
|
|
279
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Stop the running process execution via the api.
|
|
273
|
+
*/
|
|
280
274
|
ProcessExecution.prototype.stop = function stop() {
|
|
281
275
|
this.getApi().stop();
|
|
282
276
|
};
|
|
283
277
|
|
|
278
|
+
/**
|
|
279
|
+
* List currently postponed children as Api wrappers.
|
|
280
|
+
* @param {import('#types').filterPostponed} [filterFn]
|
|
281
|
+
*/
|
|
284
282
|
ProcessExecution.prototype.getPostponed = function getPostponed(filterFn) {
|
|
285
283
|
const result = [];
|
|
286
|
-
for (const msg of this[
|
|
284
|
+
for (const msg of this[K_ELEMENTS].postponed) {
|
|
287
285
|
const api = this._getChildApi(msg);
|
|
288
286
|
if (!api) continue;
|
|
289
287
|
if (filterFn && !filterFn(api)) continue;
|
|
@@ -292,9 +290,12 @@ ProcessExecution.prototype.getPostponed = function getPostponed(filterFn) {
|
|
|
292
290
|
return result;
|
|
293
291
|
};
|
|
294
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Queue a discard message that propagates to all running children.
|
|
295
|
+
*/
|
|
295
296
|
ProcessExecution.prototype.discard = function discard() {
|
|
296
|
-
this[
|
|
297
|
-
|
|
297
|
+
this[K_STATUS] = 'discard';
|
|
298
|
+
this[K_ACTIVITY_Q].queueMessage(
|
|
298
299
|
{ routingKey: 'execution.discard' },
|
|
299
300
|
{
|
|
300
301
|
id: this.id,
|
|
@@ -305,8 +306,11 @@ ProcessExecution.prototype.discard = function discard() {
|
|
|
305
306
|
);
|
|
306
307
|
};
|
|
307
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Queue a cancel message that propagates to all running children.
|
|
311
|
+
*/
|
|
308
312
|
ProcessExecution.prototype.cancel = function discard() {
|
|
309
|
-
|
|
313
|
+
this[K_ACTIVITY_Q].queueMessage(
|
|
310
314
|
{ routingKey: 'execution.cancel' },
|
|
311
315
|
{
|
|
312
316
|
id: this.id,
|
|
@@ -317,24 +321,45 @@ ProcessExecution.prototype.cancel = function discard() {
|
|
|
317
321
|
);
|
|
318
322
|
};
|
|
319
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Get child activities in the process scope.
|
|
326
|
+
* @returns {import('#types').Activity[]}
|
|
327
|
+
*/
|
|
320
328
|
ProcessExecution.prototype.getActivities = function getActivities() {
|
|
321
|
-
return this[
|
|
329
|
+
return this[K_ELEMENTS].children.slice();
|
|
322
330
|
};
|
|
323
331
|
|
|
332
|
+
/**
|
|
333
|
+
* @param {string} activityId
|
|
334
|
+
* @returns {import('#types').Activity}
|
|
335
|
+
*/
|
|
324
336
|
ProcessExecution.prototype.getActivityById = function getActivityById(activityId) {
|
|
325
|
-
return this[
|
|
337
|
+
return this[K_ELEMENTS].children.find((child) => child.id === activityId);
|
|
326
338
|
};
|
|
327
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Get sequence flows in the process scope.
|
|
342
|
+
* @returns {import('#types').SequenceFlow}
|
|
343
|
+
*/
|
|
328
344
|
ProcessExecution.prototype.getSequenceFlows = function getSequenceFlows() {
|
|
329
|
-
return this[
|
|
345
|
+
return this[K_ELEMENTS].flows.slice();
|
|
330
346
|
};
|
|
331
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Get associations in the process scope.
|
|
350
|
+
* @returns {import('../flows/Association.js').Association}
|
|
351
|
+
*/
|
|
332
352
|
ProcessExecution.prototype.getAssociations = function getAssociations() {
|
|
333
|
-
return this[
|
|
353
|
+
return this[K_ELEMENTS].associations.slice();
|
|
334
354
|
};
|
|
335
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Resolve a process or child Api for the given message.
|
|
358
|
+
* @param {import('#types').ElementBrokerMessage} [message]
|
|
359
|
+
* @returns {import('#types').IApi<import('#types').Process>}
|
|
360
|
+
*/
|
|
336
361
|
ProcessExecution.prototype.getApi = function getApi(message) {
|
|
337
|
-
if (!message) return ProcessApi(this.broker, this[
|
|
362
|
+
if (!message) return ProcessApi(this.broker, this[K_EXECUTE_MESSAGE]);
|
|
338
363
|
|
|
339
364
|
const content = message.content;
|
|
340
365
|
|
|
@@ -343,7 +368,7 @@ ProcessExecution.prototype.getApi = function getApi(message) {
|
|
|
343
368
|
}
|
|
344
369
|
|
|
345
370
|
const api = ProcessApi(this.broker, message);
|
|
346
|
-
const postponed = this[
|
|
371
|
+
const postponed = this[K_ELEMENTS].postponed;
|
|
347
372
|
const self = this;
|
|
348
373
|
|
|
349
374
|
api.getExecuting = function getExecuting() {
|
|
@@ -358,36 +383,42 @@ ProcessExecution.prototype.getApi = function getApi(message) {
|
|
|
358
383
|
return api;
|
|
359
384
|
};
|
|
360
385
|
|
|
386
|
+
/** @internal */
|
|
361
387
|
ProcessExecution.prototype._start = function start() {
|
|
362
|
-
if (!this[
|
|
388
|
+
if (!this[K_ELEMENTS].children.length) {
|
|
363
389
|
return this._complete('completed');
|
|
364
390
|
}
|
|
365
391
|
|
|
366
|
-
this[
|
|
392
|
+
this[K_STATUS] = 'start';
|
|
367
393
|
|
|
368
|
-
const executeContent = { ...this[
|
|
394
|
+
const executeContent = { ...this[K_EXECUTE_MESSAGE].content, state: this.status };
|
|
369
395
|
|
|
370
396
|
this.broker.publish(this._exchangeName, 'execute.start', cloneContent(executeContent));
|
|
371
397
|
|
|
372
|
-
const { startActivities, postponed, detachedActivities } = this[
|
|
373
|
-
|
|
374
|
-
for (const a of startActivities) a.shake();
|
|
375
|
-
}
|
|
398
|
+
const { startActivities, postponed, detachedActivities } = this[K_ELEMENTS];
|
|
399
|
+
this._shakeOnStart();
|
|
376
400
|
|
|
377
401
|
for (const a of startActivities) a.init();
|
|
378
|
-
this[
|
|
402
|
+
this[K_STATUS] = 'executing';
|
|
379
403
|
for (const a of startActivities) a.run();
|
|
380
404
|
|
|
405
|
+
if (!startActivities.size) {
|
|
406
|
+
for (const a of this[K_ELEMENTS].triggeredByEvent) {
|
|
407
|
+
if (a.isCatching && !a.isRunning) a.run();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
381
411
|
postponed.clear();
|
|
382
412
|
detachedActivities.clear();
|
|
383
|
-
this[
|
|
413
|
+
this[K_ACTIVITY_Q].assertConsumer(this[K_MESSAGE_HANDLERS].onChildMessage, {
|
|
384
414
|
prefetch: 1000,
|
|
385
415
|
consumerTag: `_process-activity-${this.executionId}`,
|
|
386
416
|
});
|
|
387
417
|
};
|
|
388
418
|
|
|
419
|
+
/** @internal */
|
|
389
420
|
ProcessExecution.prototype._activate = function activate() {
|
|
390
|
-
const { onApiMessage, onMessageFlowEvent, onActivityEvent } = this[
|
|
421
|
+
const { onApiMessage, onMessageFlowEvent, onActivityEvent } = this[K_MESSAGE_HANDLERS];
|
|
391
422
|
|
|
392
423
|
if (!this.isSubProcess) {
|
|
393
424
|
this.broker.consume('api-q', onApiMessage, {
|
|
@@ -403,7 +434,7 @@ ProcessExecution.prototype._activate = function activate() {
|
|
|
403
434
|
});
|
|
404
435
|
}
|
|
405
436
|
|
|
406
|
-
const { outboundMessageFlows, flows, associations, startActivities, triggeredByEvent, children } = this[
|
|
437
|
+
const { outboundMessageFlows, flows, associations, startActivities, triggeredByEvent, convergingGateways, children } = this[K_ELEMENTS];
|
|
407
438
|
|
|
408
439
|
for (const flow of outboundMessageFlows) {
|
|
409
440
|
flow.activate();
|
|
@@ -433,6 +464,7 @@ ProcessExecution.prototype._activate = function activate() {
|
|
|
433
464
|
startActivities.clear();
|
|
434
465
|
triggeredByEvent.clear();
|
|
435
466
|
|
|
467
|
+
let startEventCount = 0;
|
|
436
468
|
for (const activity of children) {
|
|
437
469
|
if (activity.placeholder) continue;
|
|
438
470
|
activity.activate(this);
|
|
@@ -441,20 +473,26 @@ ProcessExecution.prototype._activate = function activate() {
|
|
|
441
473
|
consumerTag: '_process-activity-consumer',
|
|
442
474
|
priority: 200,
|
|
443
475
|
});
|
|
444
|
-
if (activity.isStart)
|
|
445
|
-
|
|
476
|
+
if (activity.isStart) {
|
|
477
|
+
startActivities.add(activity);
|
|
478
|
+
if (activity.isStartEvent) startEventCount++;
|
|
479
|
+
}
|
|
480
|
+
if (activity.triggeredByEvent || activity.isCatching) triggeredByEvent.add(activity);
|
|
481
|
+
if (activity.isParallelGateway) convergingGateways.add(activity);
|
|
446
482
|
}
|
|
447
483
|
|
|
448
|
-
this[
|
|
484
|
+
this[K_ELEMENTS].startEventCount = startEventCount;
|
|
485
|
+
this[K_ACTIVATED] = true;
|
|
449
486
|
};
|
|
450
487
|
|
|
488
|
+
/** @internal */
|
|
451
489
|
ProcessExecution.prototype._deactivate = function deactivate() {
|
|
452
490
|
const broker = this.broker;
|
|
453
491
|
const executionId = this.executionId;
|
|
454
492
|
broker.cancel(`_process-api-consumer-${executionId}`);
|
|
455
493
|
broker.cancel(`_process-activity-${executionId}`);
|
|
456
494
|
|
|
457
|
-
const { children, flows, associations, outboundMessageFlows } = this[
|
|
495
|
+
const { children, flows, associations, outboundMessageFlows } = this[K_ELEMENTS];
|
|
458
496
|
|
|
459
497
|
for (const activity of children) {
|
|
460
498
|
if (activity.placeholder) continue;
|
|
@@ -475,9 +513,108 @@ ProcessExecution.prototype._deactivate = function deactivate() {
|
|
|
475
513
|
flow.broker.cancel('_process-message-consumer');
|
|
476
514
|
}
|
|
477
515
|
|
|
478
|
-
this[
|
|
516
|
+
this[K_ACTIVATED] = false;
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Discover converging parallel gateway peers for the peer monitor, reusing already discovered ones.
|
|
521
|
+
* @internal
|
|
522
|
+
*/
|
|
523
|
+
ProcessExecution.prototype._shakeOnStart = function shakeOnStart() {
|
|
524
|
+
const convergingGateways = this[K_ELEMENTS].convergingGateways;
|
|
525
|
+
if (!convergingGateways.size) return;
|
|
526
|
+
|
|
527
|
+
if (this._peersDiscovered()) {
|
|
528
|
+
this._debug(`reuse discovered parallel gateway peers (${convergingGateways.size})`);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
this._shakeElements();
|
|
533
|
+
this._debug(`forced shake to discover converging gateway peers (${convergingGateways.size})`);
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Whether every converging parallel gateway has discovered its peers in this runtime instance.
|
|
538
|
+
* Peers are a runtime cache and absent after recover, so a changed source is reshaken.
|
|
539
|
+
* @internal
|
|
540
|
+
*/
|
|
541
|
+
ProcessExecution.prototype._peersDiscovered = function peersDiscovered() {
|
|
542
|
+
const convergingGateways = this[K_ELEMENTS].convergingGateways;
|
|
543
|
+
for (const gateway of convergingGateways) {
|
|
544
|
+
if (!gateway[K_PEERS_DISCOVERED]) return false;
|
|
545
|
+
}
|
|
546
|
+
return true;
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
/** @internal */
|
|
550
|
+
ProcessExecution.prototype._shakeElements = function shakeElements(fromId) {
|
|
551
|
+
let executing = true;
|
|
552
|
+
const id = this.id;
|
|
553
|
+
if (!this.isRunning) {
|
|
554
|
+
executing = false;
|
|
555
|
+
this.executionId = getUniqueId(id);
|
|
556
|
+
this._activate();
|
|
557
|
+
}
|
|
558
|
+
const toShake = fromId ? [this.getActivityById(fromId)].filter(Boolean) : this[K_ELEMENTS].startActivities;
|
|
559
|
+
|
|
560
|
+
const result = {
|
|
561
|
+
sequences: new Map(),
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const convergingGateways = new Map();
|
|
565
|
+
const consumerTag = `_shaker-${this.executionId}`;
|
|
566
|
+
|
|
567
|
+
this.broker.subscribeTmp(
|
|
568
|
+
'event',
|
|
569
|
+
'*.shake.*',
|
|
570
|
+
(routingKey, { content }) => {
|
|
571
|
+
if (content.parent.id !== this.id) return;
|
|
572
|
+
|
|
573
|
+
switch (routingKey) {
|
|
574
|
+
case 'activity.shake.join': {
|
|
575
|
+
const join = convergingGateways.get(content.join);
|
|
576
|
+
if (!join) {
|
|
577
|
+
convergingGateways.set(content.join, content);
|
|
578
|
+
} else {
|
|
579
|
+
join.sequence = join.sequence.concat(content.sequence);
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
case 'flow.shake.loop':
|
|
584
|
+
case 'activity.shake.linked':
|
|
585
|
+
case 'activity.shake.end': {
|
|
586
|
+
const { id: shakeId, parent: shakeParent } = content;
|
|
587
|
+
if (shakeParent.id !== id) return;
|
|
588
|
+
|
|
589
|
+
let seqnce;
|
|
590
|
+
if (!(seqnce = result.sequences.get(shakeId))) {
|
|
591
|
+
seqnce = [];
|
|
592
|
+
result.sequences.set(shakeId, seqnce);
|
|
593
|
+
}
|
|
594
|
+
seqnce.push({ ...content, isLooped: routingKey === 'flow.shake.loop' });
|
|
595
|
+
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
{ noAck: true, consumerTag }
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
for (const a of toShake) a.shake();
|
|
604
|
+
|
|
605
|
+
for (const [aid, c] of convergingGateways.entries()) {
|
|
606
|
+
this._debug(`manual shake of converging gateway <${aid}>`);
|
|
607
|
+
this.getActivityById(aid).broker.publish('api', 'activity.shake.continue', c, { type: 'shake' });
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (!executing) this._deactivate();
|
|
611
|
+
|
|
612
|
+
this.broker.cancel(consumerTag);
|
|
613
|
+
|
|
614
|
+
return result;
|
|
479
615
|
};
|
|
480
616
|
|
|
617
|
+
/** @internal */
|
|
481
618
|
ProcessExecution.prototype._onDelegateEvent = function onDelegateEvent(message) {
|
|
482
619
|
const eventType = message.properties.type;
|
|
483
620
|
let delegate = true;
|
|
@@ -489,8 +626,8 @@ ProcessExecution.prototype._onDelegateEvent = function onDelegateEvent(message)
|
|
|
489
626
|
this._debug(`delegate ${eventType} anonymous event`);
|
|
490
627
|
}
|
|
491
628
|
|
|
492
|
-
for (const activity of this[
|
|
493
|
-
if (activity.getStartActivities({ referenceId: content.message?.id, referenceType: eventType }).length) {
|
|
629
|
+
for (const activity of this[K_ELEMENTS].triggeredByEvent) {
|
|
630
|
+
if (activity.isSubProcess && activity.getStartActivities({ referenceId: content.message?.id, referenceType: eventType }).length) {
|
|
494
631
|
delegate = false;
|
|
495
632
|
activity.run(content.message);
|
|
496
633
|
}
|
|
@@ -501,17 +638,20 @@ ProcessExecution.prototype._onDelegateEvent = function onDelegateEvent(message)
|
|
|
501
638
|
return delegate;
|
|
502
639
|
};
|
|
503
640
|
|
|
641
|
+
/** @internal */
|
|
504
642
|
ProcessExecution.prototype._onMessageFlowEvent = function onMessageFlowEvent(routingKey, message) {
|
|
505
643
|
this.broker.publish('message', routingKey, cloneContent(message.content), message.properties);
|
|
506
644
|
};
|
|
507
645
|
|
|
646
|
+
/** @internal */
|
|
508
647
|
ProcessExecution.prototype._onActivityEvent = function onActivityEvent(routingKey, message) {
|
|
509
|
-
|
|
648
|
+
const { fields, content, properties } = message;
|
|
649
|
+
|
|
650
|
+
if (fields.redelivered && properties.persistent === false) return;
|
|
510
651
|
|
|
511
|
-
const content = message.content;
|
|
512
652
|
const parent = (content.parent = content.parent || {});
|
|
513
|
-
let delegate =
|
|
514
|
-
const shaking =
|
|
653
|
+
let delegate = properties.delegate;
|
|
654
|
+
const shaking = properties.type === 'shake';
|
|
515
655
|
|
|
516
656
|
const isDirectChild = content.parent.id === this.id;
|
|
517
657
|
if (isDirectChild) {
|
|
@@ -522,14 +662,14 @@ ProcessExecution.prototype._onActivityEvent = function onActivityEvent(routingKe
|
|
|
522
662
|
|
|
523
663
|
if (delegate) delegate = this._onDelegateEvent(message);
|
|
524
664
|
|
|
525
|
-
this[
|
|
526
|
-
this.broker.publish('event', routingKey, content, { ...
|
|
527
|
-
if (shaking) return
|
|
665
|
+
this[K_TRACKER].track(routingKey, message);
|
|
666
|
+
this.broker.publish('event', routingKey, content, { ...properties, delegate, mandatory: false });
|
|
667
|
+
if (shaking) return;
|
|
528
668
|
if (!isDirectChild) return;
|
|
529
669
|
|
|
530
670
|
switch (routingKey) {
|
|
531
671
|
case 'process.terminate':
|
|
532
|
-
return this[
|
|
672
|
+
return this[K_ACTIVITY_Q].queueMessage({ routingKey: 'execution.terminate' }, cloneContent(content), {
|
|
533
673
|
type: 'terminate',
|
|
534
674
|
persistent: true,
|
|
535
675
|
});
|
|
@@ -537,9 +677,10 @@ ProcessExecution.prototype._onActivityEvent = function onActivityEvent(routingKe
|
|
|
537
677
|
return;
|
|
538
678
|
}
|
|
539
679
|
|
|
540
|
-
this[
|
|
680
|
+
this[K_ACTIVITY_Q].queueMessage(message.fields, cloneContent(content), { persistent: true, ...message.properties });
|
|
541
681
|
};
|
|
542
682
|
|
|
683
|
+
/** @internal */
|
|
543
684
|
ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey, message) {
|
|
544
685
|
if (message.fields.redelivered && message.properties.persistent === false) return message.ack();
|
|
545
686
|
|
|
@@ -557,7 +698,7 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
557
698
|
return this._onDiscard(message);
|
|
558
699
|
case 'execution.discard.detached': {
|
|
559
700
|
message.ack();
|
|
560
|
-
for (const detached of this[
|
|
701
|
+
for (const detached of this[K_ELEMENTS].detachedActivities) {
|
|
561
702
|
this._getChildApi(detached).discard();
|
|
562
703
|
}
|
|
563
704
|
return;
|
|
@@ -567,7 +708,7 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
567
708
|
return this._onCancel(message);
|
|
568
709
|
case 'activity.error.caught': {
|
|
569
710
|
let prevMsg;
|
|
570
|
-
for (const msg of this[
|
|
711
|
+
for (const msg of this[K_ELEMENTS].postponed) {
|
|
571
712
|
if (msg.content.executionId === content.executionId) {
|
|
572
713
|
prevMsg = msg;
|
|
573
714
|
break;
|
|
@@ -576,7 +717,6 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
576
717
|
if (!prevMsg) return message.ack();
|
|
577
718
|
break;
|
|
578
719
|
}
|
|
579
|
-
case 'flow.looped':
|
|
580
720
|
case 'activity.leave':
|
|
581
721
|
return this._onChildCompleted(message);
|
|
582
722
|
}
|
|
@@ -585,7 +725,7 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
585
725
|
|
|
586
726
|
switch (routingKey) {
|
|
587
727
|
case 'activity.detach': {
|
|
588
|
-
this[
|
|
728
|
+
this[K_ELEMENTS].detachedActivities.add(cloneMessage(message));
|
|
589
729
|
break;
|
|
590
730
|
}
|
|
591
731
|
case 'activity.cancel': {
|
|
@@ -604,16 +744,22 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
604
744
|
|
|
605
745
|
break;
|
|
606
746
|
}
|
|
747
|
+
case 'activity.end': {
|
|
748
|
+
if (!(content.isStartEvent || this.getActivityById(content.id)?.isStartEvent)) break;
|
|
749
|
+
if (this[K_ELEMENTS].startEventCount <= 1) break;
|
|
750
|
+
this._discardArmedStartEvents(content.id);
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
607
753
|
case 'activity.error': {
|
|
608
754
|
let eventCaughtBy;
|
|
609
|
-
for (const msg of this[
|
|
755
|
+
for (const msg of this[K_ELEMENTS].postponed) {
|
|
610
756
|
if (msg.fields.routingKey === 'activity.catch' && msg.content.source?.executionId === content.executionId) {
|
|
611
757
|
eventCaughtBy = msg;
|
|
612
758
|
break;
|
|
613
759
|
}
|
|
614
760
|
}
|
|
615
761
|
if (eventCaughtBy) {
|
|
616
|
-
this[
|
|
762
|
+
this[K_ACTIVITY_Q].queueMessage({ routingKey: 'activity.error.caught' }, cloneContent(content), {
|
|
617
763
|
persistent: true,
|
|
618
764
|
...message.properties,
|
|
619
765
|
});
|
|
@@ -624,14 +770,16 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
624
770
|
}
|
|
625
771
|
};
|
|
626
772
|
|
|
773
|
+
/** @internal */
|
|
627
774
|
ProcessExecution.prototype._stateChangeMessage = function stateChangeMessage(message, postponeMessage) {
|
|
628
775
|
const previousMsg = this._popPostponed(message.content);
|
|
629
776
|
if (previousMsg) previousMsg.ack();
|
|
630
|
-
if (postponeMessage) this[
|
|
777
|
+
if (postponeMessage) this[K_ELEMENTS].postponed.add(message);
|
|
631
778
|
};
|
|
632
779
|
|
|
780
|
+
/** @internal */
|
|
633
781
|
ProcessExecution.prototype._popPostponed = function popPostponed(byContent) {
|
|
634
|
-
const { postponed, detachedActivities } = this[
|
|
782
|
+
const { postponed, detachedActivities } = this[K_ELEMENTS];
|
|
635
783
|
|
|
636
784
|
let postponedMsg;
|
|
637
785
|
if (byContent.sequenceId) {
|
|
@@ -663,13 +811,20 @@ ProcessExecution.prototype._popPostponed = function popPostponed(byContent) {
|
|
|
663
811
|
return postponedMsg;
|
|
664
812
|
};
|
|
665
813
|
|
|
814
|
+
/** @internal */
|
|
666
815
|
ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message) {
|
|
667
816
|
this._stateChangeMessage(message, false);
|
|
668
817
|
if (message.fields.redelivered) return message.ack();
|
|
669
818
|
|
|
670
|
-
const { id, type,
|
|
819
|
+
const { id, type, isParallelGateway } = message.content;
|
|
820
|
+
|
|
821
|
+
if (isParallelGateway) {
|
|
822
|
+
for (const inb of message.content.inbound) {
|
|
823
|
+
this._popPostponed(inb)?.ack();
|
|
824
|
+
}
|
|
825
|
+
}
|
|
671
826
|
|
|
672
|
-
const { postponed, detachedActivities
|
|
827
|
+
const { postponed, detachedActivities } = this[K_ELEMENTS];
|
|
673
828
|
const postponedCount = postponed.size;
|
|
674
829
|
|
|
675
830
|
if (!postponedCount) {
|
|
@@ -679,10 +834,10 @@ ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message
|
|
|
679
834
|
}
|
|
680
835
|
|
|
681
836
|
message.ack();
|
|
682
|
-
this._debug(`left <${id}> (${type}), pending activities ${postponedCount}`);
|
|
837
|
+
this._debug(`left <${id}> (${type}), pending activities ${postponedCount} ${[...postponed].map((m) => m.content.id)}`);
|
|
683
838
|
|
|
684
839
|
if (postponedCount && postponedCount === detachedActivities.size) {
|
|
685
|
-
return this[
|
|
840
|
+
return this[K_ACTIVITY_Q].queueMessage(
|
|
686
841
|
{ routingKey: 'execution.discard.detached' },
|
|
687
842
|
{
|
|
688
843
|
id: this.id,
|
|
@@ -692,21 +847,9 @@ ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message
|
|
|
692
847
|
{ type: 'cancel' }
|
|
693
848
|
);
|
|
694
849
|
}
|
|
695
|
-
|
|
696
|
-
if (isEnd && startActivities.size) {
|
|
697
|
-
const startSequences = this[kElements].startSequences;
|
|
698
|
-
for (const msg of postponed) {
|
|
699
|
-
const postponedId = msg.content.id;
|
|
700
|
-
const startSequence = startSequences[postponedId];
|
|
701
|
-
if (startSequence) {
|
|
702
|
-
if (startSequence.content.sequence.some(({ id: sid }) => sid === id)) {
|
|
703
|
-
this._getChildApi(msg).discard();
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
850
|
};
|
|
709
851
|
|
|
852
|
+
/** @internal */
|
|
710
853
|
ProcessExecution.prototype._stopExecution = function stopExecution(message) {
|
|
711
854
|
const postponedCount = this.postponedCount;
|
|
712
855
|
this._debug(`stop process execution (stop child executions ${postponedCount})`);
|
|
@@ -714,21 +857,22 @@ ProcessExecution.prototype._stopExecution = function stopExecution(message) {
|
|
|
714
857
|
for (const api of this.getPostponed()) api.stop();
|
|
715
858
|
}
|
|
716
859
|
this._deactivate();
|
|
717
|
-
this[
|
|
860
|
+
this[K_STOPPED] = true;
|
|
718
861
|
return this.broker.publish(
|
|
719
862
|
this._exchangeName,
|
|
720
863
|
`execution.stopped.${this.executionId}`,
|
|
721
864
|
{
|
|
722
|
-
...this[
|
|
865
|
+
...this[K_EXECUTE_MESSAGE].content,
|
|
723
866
|
...(message && message.content),
|
|
724
867
|
},
|
|
725
868
|
{ type: 'stopped', persistent: false }
|
|
726
869
|
);
|
|
727
870
|
};
|
|
728
871
|
|
|
872
|
+
/** @internal */
|
|
729
873
|
ProcessExecution.prototype._onDiscard = function onDiscard() {
|
|
730
874
|
this._deactivate();
|
|
731
|
-
const postponed = this[
|
|
875
|
+
const postponed = this[K_ELEMENTS].postponed;
|
|
732
876
|
const running = new Set(postponed);
|
|
733
877
|
postponed.clear();
|
|
734
878
|
|
|
@@ -742,23 +886,24 @@ ProcessExecution.prototype._onDiscard = function onDiscard() {
|
|
|
742
886
|
for (const msg of running) this._getChildApi(msg).discard();
|
|
743
887
|
}
|
|
744
888
|
|
|
745
|
-
this[
|
|
889
|
+
this[K_ACTIVITY_Q].purge();
|
|
746
890
|
return this._complete('discard');
|
|
747
891
|
};
|
|
748
892
|
|
|
893
|
+
/** @internal */
|
|
749
894
|
ProcessExecution.prototype._onCancel = function onCancel() {
|
|
750
|
-
const postponed = this[
|
|
895
|
+
const postponed = this[K_ELEMENTS].postponed;
|
|
751
896
|
const running = new Set(postponed);
|
|
752
897
|
|
|
753
898
|
const isTransaction = this.isTransaction;
|
|
754
899
|
|
|
755
900
|
if (isTransaction) {
|
|
756
901
|
this._debug(`cancel transaction execution (cancel child executions ${running.size})`);
|
|
757
|
-
this[
|
|
902
|
+
this[K_STATUS] = 'cancel';
|
|
758
903
|
this.broker.publish(
|
|
759
904
|
'event',
|
|
760
905
|
'transaction.cancel',
|
|
761
|
-
cloneMessage(this[
|
|
906
|
+
cloneMessage(this[K_EXECUTE_MESSAGE], {
|
|
762
907
|
state: 'cancel',
|
|
763
908
|
})
|
|
764
909
|
);
|
|
@@ -778,6 +923,7 @@ ProcessExecution.prototype._onCancel = function onCancel() {
|
|
|
778
923
|
}
|
|
779
924
|
};
|
|
780
925
|
|
|
926
|
+
/** @internal */
|
|
781
927
|
ProcessExecution.prototype._onApiMessage = function onApiMessage(routingKey, message) {
|
|
782
928
|
if (message.properties.delegate) {
|
|
783
929
|
return this._delegateApiMessage(routingKey, message);
|
|
@@ -797,11 +943,12 @@ ProcessExecution.prototype._onApiMessage = function onApiMessage(routingKey, mes
|
|
|
797
943
|
case 'discard':
|
|
798
944
|
return this.discard(message);
|
|
799
945
|
case 'stop':
|
|
800
|
-
this[
|
|
946
|
+
this[K_ACTIVITY_Q].queueMessage({ routingKey: 'execution.stop' }, cloneContent(message.content), { persistent: false });
|
|
801
947
|
break;
|
|
802
948
|
}
|
|
803
949
|
};
|
|
804
950
|
|
|
951
|
+
/** @internal */
|
|
805
952
|
ProcessExecution.prototype._delegateApiMessage = function delegateApiMessage(routingKey, message, continueOnConsumed) {
|
|
806
953
|
const correlationId = message.properties.correlationId || getUniqueId(this.executionId);
|
|
807
954
|
this._debug(`delegate api ${routingKey} message to children, with correlationId <${correlationId}>`);
|
|
@@ -820,8 +967,9 @@ ProcessExecution.prototype._delegateApiMessage = function delegateApiMessage(rou
|
|
|
820
967
|
{ consumerTag: `_ct-delegate-${correlationId}`, noAck: true }
|
|
821
968
|
);
|
|
822
969
|
|
|
823
|
-
for (const child of this[
|
|
970
|
+
for (const child of this[K_ELEMENTS].children) {
|
|
824
971
|
if (child.placeholder) continue;
|
|
972
|
+
|
|
825
973
|
child.broker.publish('api', routingKey, cloneContent(message.content), message.properties);
|
|
826
974
|
if (consumed && !continueOnConsumed) break;
|
|
827
975
|
}
|
|
@@ -829,9 +977,10 @@ ProcessExecution.prototype._delegateApiMessage = function delegateApiMessage(rou
|
|
|
829
977
|
return broker.cancel(`_ct-delegate-${correlationId}`);
|
|
830
978
|
};
|
|
831
979
|
|
|
980
|
+
/** @internal */
|
|
832
981
|
ProcessExecution.prototype._complete = function complete(completionType, content) {
|
|
833
982
|
this._deactivate();
|
|
834
|
-
this[
|
|
983
|
+
this[K_COMPLETED] = true;
|
|
835
984
|
|
|
836
985
|
const status = this.status;
|
|
837
986
|
switch (this.status) {
|
|
@@ -844,16 +993,16 @@ ProcessExecution.prototype._complete = function complete(completionType, content
|
|
|
844
993
|
break;
|
|
845
994
|
default:
|
|
846
995
|
this._debug(`process execution ${completionType}`);
|
|
847
|
-
this[
|
|
996
|
+
this[K_STATUS] = completionType;
|
|
848
997
|
}
|
|
849
998
|
|
|
850
999
|
const broker = this.broker;
|
|
851
|
-
this[
|
|
1000
|
+
this[K_ACTIVITY_Q].delete();
|
|
852
1001
|
|
|
853
|
-
|
|
1002
|
+
broker.publish(
|
|
854
1003
|
this._exchangeName,
|
|
855
1004
|
`execution.${completionType}.${this.executionId}`,
|
|
856
|
-
cloneContent(this[
|
|
1005
|
+
cloneContent(this[K_EXECUTE_MESSAGE].content, {
|
|
857
1006
|
output: { ...this.environment.output },
|
|
858
1007
|
...content,
|
|
859
1008
|
state: completionType,
|
|
@@ -862,11 +1011,12 @@ ProcessExecution.prototype._complete = function complete(completionType, content
|
|
|
862
1011
|
);
|
|
863
1012
|
};
|
|
864
1013
|
|
|
1014
|
+
/** @internal */
|
|
865
1015
|
ProcessExecution.prototype._terminate = function terminate(message) {
|
|
866
|
-
this[
|
|
1016
|
+
this[K_STATUS] = 'terminated';
|
|
867
1017
|
this._debug('terminating process execution');
|
|
868
1018
|
|
|
869
|
-
const postponed = this[
|
|
1019
|
+
const postponed = this[K_ELEMENTS].postponed;
|
|
870
1020
|
const running = new Set(postponed);
|
|
871
1021
|
postponed.clear();
|
|
872
1022
|
|
|
@@ -881,25 +1031,67 @@ ProcessExecution.prototype._terminate = function terminate(message) {
|
|
|
881
1031
|
msg.ack();
|
|
882
1032
|
}
|
|
883
1033
|
|
|
884
|
-
this[
|
|
1034
|
+
this[K_ACTIVITY_Q].purge();
|
|
885
1035
|
};
|
|
886
1036
|
|
|
1037
|
+
/** @internal */
|
|
887
1038
|
ProcessExecution.prototype._getFlowById = function getFlowById(flowId) {
|
|
888
|
-
return this[
|
|
1039
|
+
return this[K_ELEMENTS].flows.find((f) => f.id === flowId);
|
|
889
1040
|
};
|
|
890
1041
|
|
|
1042
|
+
/** @internal */
|
|
891
1043
|
ProcessExecution.prototype._getAssociationById = function getAssociationById(associationId) {
|
|
892
|
-
return this[
|
|
1044
|
+
return this[K_ELEMENTS].associations.find((a) => a.id === associationId);
|
|
893
1045
|
};
|
|
894
1046
|
|
|
1047
|
+
/** @internal */
|
|
895
1048
|
ProcessExecution.prototype._getMessageFlowById = function getMessageFlowById(flowId) {
|
|
896
|
-
return this[
|
|
1049
|
+
return this[K_ELEMENTS].outboundMessageFlows.find((f) => f.id === flowId);
|
|
897
1050
|
};
|
|
898
1051
|
|
|
1052
|
+
/** @internal */
|
|
899
1053
|
ProcessExecution.prototype._getChildById = function getChildById(childId) {
|
|
900
1054
|
return this.getActivityById(childId) || this._getFlowById(childId);
|
|
901
1055
|
};
|
|
902
1056
|
|
|
1057
|
+
/**
|
|
1058
|
+
* Discard the other armed start events once one mutually exclusive entry point wins.
|
|
1059
|
+
* Resolves the start-event flag from the live activity so recovered pre-flag state is handled.
|
|
1060
|
+
* @internal
|
|
1061
|
+
*/
|
|
1062
|
+
ProcessExecution.prototype._discardArmedStartEvents = function discardArmedStartEvents(winnerId) {
|
|
1063
|
+
const elements = this[K_ELEMENTS];
|
|
1064
|
+
const startPeers = [];
|
|
1065
|
+
for (const msg of elements.postponed) {
|
|
1066
|
+
const peerId = msg.content.id;
|
|
1067
|
+
if (peerId === winnerId) continue;
|
|
1068
|
+
if (this.getActivityById(peerId)?.isStartEvent) startPeers.push(msg);
|
|
1069
|
+
}
|
|
1070
|
+
if (!startPeers.length) return;
|
|
1071
|
+
elements.startEventCount = 0;
|
|
1072
|
+
for (const msg of startPeers) this._getChildApi(msg).discard();
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* On resume of a state from an older major, discard start events left armed when another entry
|
|
1077
|
+
* point already won before recovery. The winning start event's `activity.end` cannot replay, so
|
|
1078
|
+
* the live discard trigger never fires.
|
|
1079
|
+
* @internal
|
|
1080
|
+
*/
|
|
1081
|
+
ProcessExecution.prototype._reconcileStartEvents = function reconcileStartEvents() {
|
|
1082
|
+
const elements = this[K_ELEMENTS];
|
|
1083
|
+
if (elements.startEventCount <= 1) return;
|
|
1084
|
+
if (!(this[K_RECOVERED_VERSION] < STATE_VERSION)) return;
|
|
1085
|
+
|
|
1086
|
+
for (const child of elements.children) {
|
|
1087
|
+
if (child.isStartEvent && child.counters.taken) {
|
|
1088
|
+
this._discardArmedStartEvents();
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
/** @internal */
|
|
903
1095
|
ProcessExecution.prototype._getChildApi = function getChildApi(message) {
|
|
904
1096
|
const content = message.content;
|
|
905
1097
|
|
|
@@ -919,12 +1111,7 @@ ProcessExecution.prototype._getChildApi = function getChildApi(message) {
|
|
|
919
1111
|
}
|
|
920
1112
|
};
|
|
921
1113
|
|
|
922
|
-
|
|
923
|
-
const routingKey = message.fields.routingKey;
|
|
924
|
-
if (routingKey !== 'activity.shake.end') return;
|
|
925
|
-
this[kElements].startSequences[message.content.id] = cloneMessage(message);
|
|
926
|
-
};
|
|
927
|
-
|
|
1114
|
+
/** @internal */
|
|
928
1115
|
ProcessExecution.prototype._debug = function debugMessage(logMessage) {
|
|
929
|
-
this[
|
|
1116
|
+
this[K_PARENT].logger.debug(`<${this.executionId} (${this.id})> ${logMessage}`);
|
|
930
1117
|
};
|