bpmn-elements 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/EventBroker.js +4 -0
- package/dist/Tracker.js +89 -0
- package/dist/activity/Activity.js +47 -57
- package/dist/activity/ActivityExecution.js +6 -9
- package/dist/definition/Definition.js +23 -17
- package/dist/definition/DefinitionExecution.js +23 -0
- package/dist/eventDefinitions/CancelEventDefinition.js +20 -76
- package/dist/eventDefinitions/CompensateEventDefinition.js +54 -41
- package/dist/eventDefinitions/ConditionalEventDefinition.js +11 -2
- package/dist/eventDefinitions/ErrorEventDefinition.js +2 -0
- package/dist/events/BoundaryEvent.js +25 -10
- package/dist/flows/Association.js +0 -7
- package/dist/gateways/EventBasedGateway.js +1 -2
- package/dist/process/Process.js +5 -0
- package/dist/process/ProcessExecution.js +128 -36
- package/dist/tasks/SubProcess.js +2 -1
- package/package.json +4 -4
- package/src/EventBroker.js +1 -0
- package/src/Tracker.js +73 -0
- package/src/activity/Activity.js +45 -51
- package/src/activity/ActivityExecution.js +6 -8
- package/src/definition/Definition.js +24 -21
- package/src/definition/DefinitionExecution.js +26 -0
- package/src/eventDefinitions/CancelEventDefinition.js +22 -66
- package/src/eventDefinitions/CompensateEventDefinition.js +48 -40
- package/src/eventDefinitions/ConditionalEventDefinition.js +12 -2
- package/src/eventDefinitions/ErrorEventDefinition.js +2 -0
- package/src/events/BoundaryEvent.js +20 -8
- package/src/flows/Association.js +0 -10
- package/src/gateways/EventBasedGateway.js +1 -2
- package/src/process/Process.js +6 -0
- package/src/process/ProcessExecution.js +126 -36
- package/src/tasks/SubProcess.js +2 -1
- package/types/index.d.ts +29 -0
|
@@ -29,12 +29,16 @@ function CompensateEventDefinition(activity, eventDefinition, context) {
|
|
|
29
29
|
this.logger = environment.Logger(type.toLowerCase());
|
|
30
30
|
if (!isThrowing) {
|
|
31
31
|
this[kCompleted] = false;
|
|
32
|
-
this[kAssociations] = context.getOutboundAssociations(id)
|
|
32
|
+
this[kAssociations] = context.getOutboundAssociations(id);
|
|
33
33
|
const messageQueueName = `${reference.referenceType}-${(0, _shared.brokerSafeId)(id)}-q`;
|
|
34
34
|
this[kMessageQ] = broker.assertQueue(messageQueueName, {
|
|
35
35
|
autoDelete: false,
|
|
36
36
|
durable: true
|
|
37
37
|
});
|
|
38
|
+
this[kCompensateQ] = broker.assertQueue('compensate-q', {
|
|
39
|
+
autoDelete: false,
|
|
40
|
+
durable: true
|
|
41
|
+
});
|
|
38
42
|
broker.bindQueue(messageQueueName, 'api', `*.${reference.referenceType}.#`, {
|
|
39
43
|
durable: true,
|
|
40
44
|
priority: 400
|
|
@@ -53,6 +57,11 @@ CompensateEventDefinition.prototype.execute = function execute(executeMessage) {
|
|
|
53
57
|
CompensateEventDefinition.prototype.executeCatch = function executeCatch(executeMessage) {
|
|
54
58
|
this[kExecuteMessage] = executeMessage;
|
|
55
59
|
this[kCompleted] = false;
|
|
60
|
+
if (executeMessage.fields.routingKey === 'execute.compensating') {
|
|
61
|
+
this._debug('resumed at compensating');
|
|
62
|
+
this[kCompleted] = true;
|
|
63
|
+
return this._compensate();
|
|
64
|
+
}
|
|
56
65
|
const executeContent = executeMessage.content;
|
|
57
66
|
const {
|
|
58
67
|
executionId,
|
|
@@ -60,44 +69,34 @@ CompensateEventDefinition.prototype.executeCatch = function executeCatch(execute
|
|
|
60
69
|
} = executeContent;
|
|
61
70
|
this._debug('expect compensate');
|
|
62
71
|
const broker = this.broker;
|
|
72
|
+
broker.cancel('_convey-messages');
|
|
63
73
|
broker.assertExchange('compensate', 'topic');
|
|
64
|
-
this[kCompensateQ] = broker.assertQueue('compensate-q', {
|
|
65
|
-
durable: true,
|
|
66
|
-
autoDelete: false
|
|
67
|
-
});
|
|
68
74
|
broker.subscribeTmp('compensate', 'execute.#', this._onCollect.bind(this), {
|
|
69
75
|
noAck: true,
|
|
70
76
|
consumerTag: '_oncollect-messages'
|
|
71
77
|
});
|
|
72
|
-
broker.publish('execution', 'execute.detach', (0, _messageHelper.cloneContent)(executeContent, {
|
|
73
|
-
sourceExchange: 'execution',
|
|
74
|
-
bindExchange: 'compensate'
|
|
75
|
-
}));
|
|
76
78
|
this[kMessageQ].consume(this._onCompensateApiMessage.bind(this), {
|
|
77
79
|
noAck: true,
|
|
78
80
|
consumerTag: `_oncompensate-${executionId}`
|
|
79
81
|
});
|
|
80
82
|
if (this[kCompleted]) return;
|
|
81
|
-
|
|
82
|
-
broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {
|
|
83
|
+
broker.subscribeTmp('api', `activity.#.${parent.executionId}#`, this._onApiMessage.bind(this), {
|
|
83
84
|
noAck: true,
|
|
84
85
|
consumerTag: `_api-${executionId}`
|
|
85
86
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
bindExchange: 'compensate'
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
broker.publish('event', 'activity.detach', detachContent);
|
|
87
|
+
broker.publish('execution', 'execute.detach', (0, _messageHelper.cloneContent)(executeContent, {
|
|
88
|
+
sourceExchange: 'execution',
|
|
89
|
+
bindExchange: 'compensate',
|
|
90
|
+
expect: 'compensate'
|
|
91
|
+
}));
|
|
92
92
|
};
|
|
93
93
|
CompensateEventDefinition.prototype.executeThrow = function executeThrow(executeMessage) {
|
|
94
94
|
const executeContent = executeMessage.content;
|
|
95
95
|
const {
|
|
96
|
-
executionId,
|
|
97
96
|
parent
|
|
98
97
|
} = executeContent;
|
|
99
98
|
const parentExecutionId = parent && parent.executionId;
|
|
100
|
-
this.logger.debug(`<${
|
|
99
|
+
this.logger.debug(`<${parentExecutionId} (${this.id})> throw compensate`);
|
|
101
100
|
const broker = this.broker;
|
|
102
101
|
const throwContent = (0, _messageHelper.cloneContent)(executeContent, {
|
|
103
102
|
executionId: parentExecutionId,
|
|
@@ -120,12 +119,12 @@ CompensateEventDefinition.prototype._onCollect = function onCollect(routingKey,
|
|
|
120
119
|
}
|
|
121
120
|
};
|
|
122
121
|
CompensateEventDefinition.prototype._onCompensateApiMessage = function onCompensateApiMessage(routingKey, message) {
|
|
123
|
-
const output = message.content.message;
|
|
124
122
|
this[kCompleted] = true;
|
|
125
|
-
|
|
126
|
-
this._debug('caught compensate event');
|
|
123
|
+
const output = message.content.message;
|
|
127
124
|
const broker = this.broker;
|
|
128
125
|
const executeContent = this[kExecuteMessage].content;
|
|
126
|
+
this._stopCollect();
|
|
127
|
+
this._debug('caught compensate event');
|
|
129
128
|
const catchContent = (0, _messageHelper.cloneContent)(executeContent, {
|
|
130
129
|
message: {
|
|
131
130
|
...output
|
|
@@ -133,27 +132,42 @@ CompensateEventDefinition.prototype._onCompensateApiMessage = function onCompens
|
|
|
133
132
|
executionId: executeContent.parent.executionId
|
|
134
133
|
});
|
|
135
134
|
catchContent.parent = (0, _messageHelper.shiftParent)(catchContent.parent);
|
|
135
|
+
this[kCompensateQ].queueMessage({
|
|
136
|
+
routingKey: 'execute.compensated'
|
|
137
|
+
}, (0, _messageHelper.cloneContent)(executeContent));
|
|
138
|
+
broker.publish('execution', 'execute.compensating', (0, _messageHelper.cloneContent)(executeContent, {
|
|
139
|
+
message: {
|
|
140
|
+
...output
|
|
141
|
+
}
|
|
142
|
+
}));
|
|
136
143
|
broker.publish('event', 'activity.catch', catchContent, {
|
|
137
144
|
type: 'catch'
|
|
138
145
|
});
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
return this._compensate();
|
|
147
|
+
};
|
|
148
|
+
CompensateEventDefinition.prototype._compensate = function compensate() {
|
|
149
|
+
return this[kCompensateQ].consume(this._onCollected.bind(this), {
|
|
142
150
|
noAck: true,
|
|
143
151
|
consumerTag: '_convey-messages'
|
|
144
152
|
});
|
|
145
|
-
for (const association of this[kAssociations]) association.complete((0, _messageHelper.cloneMessage)(message));
|
|
146
|
-
function onDepleted() {
|
|
147
|
-
compensateQ.off('depleted', onDepleted);
|
|
148
|
-
return broker.publish('execution', 'execute.completed', (0, _messageHelper.cloneContent)(executeContent, {
|
|
149
|
-
output,
|
|
150
|
-
state: 'catch'
|
|
151
|
-
}));
|
|
152
|
-
}
|
|
153
153
|
};
|
|
154
154
|
CompensateEventDefinition.prototype._onCollected = function onCollected(routingKey, message) {
|
|
155
|
+
if (routingKey === 'execute.compensated') {
|
|
156
|
+
const broker = this.broker;
|
|
157
|
+
broker.cancel('_convey-messages');
|
|
158
|
+
return this.broker.publish('execution', 'execute.completed', (0, _messageHelper.cloneContent)(message.content, {
|
|
159
|
+
cancelActivity: false
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
155
162
|
for (const association of this[kAssociations]) association.take((0, _messageHelper.cloneMessage)(message));
|
|
156
163
|
};
|
|
164
|
+
CompensateEventDefinition.prototype._onDiscardApiMessage = function onDiscardApiMessage(routingKey, message) {
|
|
165
|
+
this[kCompleted] = true;
|
|
166
|
+
this._stop();
|
|
167
|
+
this[kCompensateQ].purge();
|
|
168
|
+
for (const association of this[kAssociations]) association.discard((0, _messageHelper.cloneMessage)(message));
|
|
169
|
+
return this.broker.publish('execution', 'execute.discard', (0, _messageHelper.cloneContent)(this[kExecuteMessage].content));
|
|
170
|
+
};
|
|
157
171
|
CompensateEventDefinition.prototype._onApiMessage = function onApiMessage(routingKey, message) {
|
|
158
172
|
const messageType = message.properties.type;
|
|
159
173
|
switch (messageType) {
|
|
@@ -163,27 +177,26 @@ CompensateEventDefinition.prototype._onApiMessage = function onApiMessage(routin
|
|
|
163
177
|
}
|
|
164
178
|
case 'discard':
|
|
165
179
|
{
|
|
166
|
-
this
|
|
167
|
-
this._stop();
|
|
168
|
-
for (const association of this[kAssociations]) association.discard((0, _messageHelper.cloneMessage)(message));
|
|
169
|
-
return this.broker.publish('execution', 'execute.discard', (0, _messageHelper.cloneContent)(this[kExecuteMessage].content));
|
|
180
|
+
return this._onDiscardApiMessage(routingKey, message);
|
|
170
181
|
}
|
|
171
182
|
case 'stop':
|
|
172
183
|
{
|
|
173
|
-
this._stop();
|
|
174
|
-
break;
|
|
184
|
+
return this._stop();
|
|
175
185
|
}
|
|
176
186
|
}
|
|
177
187
|
};
|
|
178
|
-
CompensateEventDefinition.prototype.
|
|
188
|
+
CompensateEventDefinition.prototype._stopCollect = function stopCollect() {
|
|
179
189
|
const broker = this.broker,
|
|
180
190
|
executionId = this.executionId;
|
|
181
191
|
broker.cancel(`_api-${executionId}`);
|
|
182
192
|
broker.cancel(`_oncompensate-${executionId}`);
|
|
183
193
|
broker.cancel('_oncollect-messages');
|
|
184
|
-
broker.cancel('_convey-messages');
|
|
185
194
|
this[kMessageQ].purge();
|
|
186
195
|
};
|
|
196
|
+
CompensateEventDefinition.prototype._stop = function stop() {
|
|
197
|
+
this._stopCollect();
|
|
198
|
+
this.broker.cancel('_convey-messages');
|
|
199
|
+
};
|
|
187
200
|
CompensateEventDefinition.prototype._debug = function debug(msg) {
|
|
188
201
|
this.logger.debug(`<${this.executionId} (${this.activity.id})> ${msg}`);
|
|
189
202
|
};
|
|
@@ -66,9 +66,12 @@ ConditionalEventDefinition.prototype.executeCatch = function executeCatch(execut
|
|
|
66
66
|
const executeContent = executeMessage.content;
|
|
67
67
|
const {
|
|
68
68
|
executionId,
|
|
69
|
-
index
|
|
69
|
+
index,
|
|
70
|
+
parent
|
|
70
71
|
} = executeContent;
|
|
71
|
-
|
|
72
|
+
const parentExecutionId = parent.executionId;
|
|
73
|
+
const broker = this.broker;
|
|
74
|
+
broker.subscribeTmp('api', `activity.#.${executionId}`, this._onCatchApiMessage.bind(this), {
|
|
72
75
|
noAck: true,
|
|
73
76
|
consumerTag: `_api-${executionId}_${index}`
|
|
74
77
|
});
|
|
@@ -81,6 +84,12 @@ ConditionalEventDefinition.prototype.executeCatch = function executeCatch(execut
|
|
|
81
84
|
priority: 300,
|
|
82
85
|
consumerTag: `_onend-${executionId}_${index}`
|
|
83
86
|
});
|
|
87
|
+
const waitContent = (0, _messageHelper.cloneContent)(executeContent, {
|
|
88
|
+
executionId: parentExecutionId,
|
|
89
|
+
condition: this.condition
|
|
90
|
+
});
|
|
91
|
+
waitContent.parent = (0, _messageHelper.shiftParent)(parent);
|
|
92
|
+
broker.publish('event', 'activity.wait', waitContent);
|
|
84
93
|
};
|
|
85
94
|
ConditionalEventDefinition.prototype._onWaitApiMessage = function onWaitApiMessage(routingKey, message) {
|
|
86
95
|
const messageType = message.properties.type;
|
|
@@ -86,6 +86,8 @@ ErrorEventDefinition.prototype.executeCatch = function executeCatch(executeMessa
|
|
|
86
86
|
consumerTag: `_onerror-${executionId}`
|
|
87
87
|
});
|
|
88
88
|
broker.publish('execution', 'execute.expect', (0, _messageHelper.cloneContent)(executeContent, {
|
|
89
|
+
pattern: 'activity.error',
|
|
90
|
+
exchange: 'execution',
|
|
89
91
|
expectRoutingKey,
|
|
90
92
|
expect: {
|
|
91
93
|
...info.message
|
|
@@ -99,7 +99,7 @@ BoundaryEventBehaviour.prototype._onExecutionMessage = function onExecutionMessa
|
|
|
99
99
|
BoundaryEventBehaviour.prototype._onCompleted = function onCompleted(_, {
|
|
100
100
|
content
|
|
101
101
|
}) {
|
|
102
|
-
if (!this.cancelActivity && !content.cancelActivity) {
|
|
102
|
+
if (content.cancelActivity === false || !this.cancelActivity && !content.cancelActivity) {
|
|
103
103
|
this._stop();
|
|
104
104
|
return this.broker.publish('execution', 'execute.completed', (0, _messageHelper.cloneContent)(content, {
|
|
105
105
|
isDefinitionScope: false,
|
|
@@ -129,25 +129,34 @@ BoundaryEventBehaviour.prototype._onExpectMessage = function onExpectMessage(_,
|
|
|
129
129
|
}) {
|
|
130
130
|
const {
|
|
131
131
|
executionId,
|
|
132
|
-
expectRoutingKey
|
|
132
|
+
expectRoutingKey,
|
|
133
|
+
pattern,
|
|
134
|
+
exchange
|
|
133
135
|
} = content;
|
|
134
136
|
const attachedTo = this.attachedTo;
|
|
135
137
|
const errorConsumerTag = `_bound-error-listener-${executionId}`;
|
|
136
138
|
this[kAttachedTags].push(errorConsumerTag);
|
|
137
|
-
attachedTo.broker.subscribeTmp('event',
|
|
138
|
-
if (
|
|
139
|
-
this.broker.publish(
|
|
139
|
+
attachedTo.broker.subscribeTmp('event', pattern, (__, message) => {
|
|
140
|
+
if (message.content.id !== attachedTo.id) return;
|
|
141
|
+
this.broker.publish(exchange, expectRoutingKey, (0, _messageHelper.cloneContent)(message.content, {
|
|
142
|
+
attachedTo: attachedTo.id
|
|
143
|
+
}), {
|
|
144
|
+
...message.properties,
|
|
145
|
+
mandatory: false
|
|
146
|
+
});
|
|
140
147
|
}, {
|
|
141
148
|
noAck: true,
|
|
142
149
|
consumerTag: errorConsumerTag,
|
|
143
|
-
priority:
|
|
150
|
+
priority: 400
|
|
144
151
|
});
|
|
145
152
|
};
|
|
146
|
-
BoundaryEventBehaviour.prototype._onDetachMessage = function onDetachMessage(_, {
|
|
147
|
-
content
|
|
148
|
-
|
|
153
|
+
BoundaryEventBehaviour.prototype._onDetachMessage = function onDetachMessage(_, message) {
|
|
154
|
+
const content = message.content;
|
|
155
|
+
const {
|
|
156
|
+
executionId,
|
|
157
|
+
parent
|
|
158
|
+
} = this[kExecuteMessage].content;
|
|
149
159
|
const id = this.id,
|
|
150
|
-
executionId = this.executionId,
|
|
151
160
|
attachedTo = this.attachedTo;
|
|
152
161
|
this.activity.logger.debug(`<${executionId} (${id})> detach from activity <${attachedTo.id}>`);
|
|
153
162
|
this._stop(true);
|
|
@@ -169,6 +178,12 @@ BoundaryEventBehaviour.prototype._onDetachMessage = function onDetachMessage(_,
|
|
|
169
178
|
}, {
|
|
170
179
|
cloneMessage: _messageHelper.cloneMessage
|
|
171
180
|
});
|
|
181
|
+
const detachContent = (0, _messageHelper.cloneContent)(content, {
|
|
182
|
+
executionId
|
|
183
|
+
});
|
|
184
|
+
detachContent.parent = parent;
|
|
185
|
+
this.activity.removeInboundListeners();
|
|
186
|
+
broker.publish('event', 'activity.detach', detachContent);
|
|
172
187
|
broker.subscribeOnce('execution', 'execute.bound.completed', (__, {
|
|
173
188
|
content: completeContent
|
|
174
189
|
}) => {
|
|
@@ -32,7 +32,6 @@ function Association(associationDef, {
|
|
|
32
32
|
this.environment = environment;
|
|
33
33
|
const logger = this.logger = environment.Logger(type.toLowerCase());
|
|
34
34
|
this[kCounters] = {
|
|
35
|
-
complete: 0,
|
|
36
35
|
take: 0,
|
|
37
36
|
discard: 0
|
|
38
37
|
};
|
|
@@ -72,12 +71,6 @@ Association.prototype.discard = function discard(content = {}) {
|
|
|
72
71
|
this._publishEvent('discard', content);
|
|
73
72
|
return true;
|
|
74
73
|
};
|
|
75
|
-
Association.prototype.complete = function complete(content = {}) {
|
|
76
|
-
this.logger.debug(`<${this.id}> completed target <${this.targetId}>`);
|
|
77
|
-
++this[kCounters].complete;
|
|
78
|
-
this._publishEvent('complete', content);
|
|
79
|
-
return true;
|
|
80
|
-
};
|
|
81
74
|
Association.prototype.getState = function getState() {
|
|
82
75
|
return this._createMessageContent({
|
|
83
76
|
counters: this.counters,
|
|
@@ -47,7 +47,6 @@ EventBasedGatewayBehaviour.prototype.execute = function execute(executeMessage)
|
|
|
47
47
|
}
|
|
48
48
|
const broker = this.activity.broker;
|
|
49
49
|
broker.subscribeOnce('api', `activity.stop.${executionId}`, () => this._stop(), {
|
|
50
|
-
noAck: true,
|
|
51
50
|
consumerTag: '_api-stop-execution'
|
|
52
51
|
});
|
|
53
52
|
this[kCompleted] = false;
|
|
@@ -58,7 +57,7 @@ EventBasedGatewayBehaviour.prototype.execute = function execute(executeMessage)
|
|
|
58
57
|
EventBasedGatewayBehaviour.prototype._onTargetCompleted = function onTargetCompleted(executeMessage, _, message, owner) {
|
|
59
58
|
const {
|
|
60
59
|
id: targetId,
|
|
61
|
-
|
|
60
|
+
executionId: targetExecutionId
|
|
62
61
|
} = message.content;
|
|
63
62
|
const executeContent = executeMessage.content;
|
|
64
63
|
const executionId = executeContent.executionId;
|
package/dist/process/Process.js
CHANGED
|
@@ -117,6 +117,11 @@ Object.defineProperty(Process.prototype, 'status', {
|
|
|
117
117
|
return this[kStatus];
|
|
118
118
|
}
|
|
119
119
|
});
|
|
120
|
+
Object.defineProperty(Process.prototype, 'activityStatus', {
|
|
121
|
+
get() {
|
|
122
|
+
return this[kExec].execution && this[kExec].execution.activityStatus || 'idle';
|
|
123
|
+
}
|
|
124
|
+
});
|
|
120
125
|
Process.prototype.init = function init(useAsExecutionId) {
|
|
121
126
|
const exec = this[kExec];
|
|
122
127
|
const initExecutionId = exec.initExecutionId = useAsExecutionId || (0, _shared.getUniqueId)(this.id);
|
|
@@ -7,6 +7,7 @@ exports.default = void 0;
|
|
|
7
7
|
var _Api = require("../Api.js");
|
|
8
8
|
var _messageHelper = require("../messageHelper.js");
|
|
9
9
|
var _shared = require("../shared.js");
|
|
10
|
+
var _Tracker = require("../Tracker.js");
|
|
10
11
|
var _default = ProcessExecution;
|
|
11
12
|
exports.default = _default;
|
|
12
13
|
const kActivated = Symbol.for('activated');
|
|
@@ -18,17 +19,20 @@ const kMessageHandlers = Symbol.for('messageHandlers');
|
|
|
18
19
|
const kParent = Symbol.for('parent');
|
|
19
20
|
const kStatus = Symbol.for('status');
|
|
20
21
|
const kStopped = Symbol.for('stopped');
|
|
22
|
+
const kTracker = Symbol.for('activity tracker');
|
|
21
23
|
function ProcessExecution(parentActivity, context) {
|
|
22
24
|
const {
|
|
23
25
|
id,
|
|
24
26
|
type,
|
|
25
27
|
broker,
|
|
26
|
-
isSubProcess
|
|
28
|
+
isSubProcess,
|
|
29
|
+
isTransaction
|
|
27
30
|
} = parentActivity;
|
|
28
31
|
this[kParent] = parentActivity;
|
|
29
32
|
this.id = id;
|
|
30
33
|
this.type = type;
|
|
31
34
|
this.isSubProcess = isSubProcess;
|
|
35
|
+
this.isTransaction = isSubProcess && isTransaction;
|
|
32
36
|
this.broker = broker;
|
|
33
37
|
this.environment = context.environment;
|
|
34
38
|
this.context = context;
|
|
@@ -52,6 +56,7 @@ function ProcessExecution(parentActivity, context) {
|
|
|
52
56
|
this[kStopped] = false;
|
|
53
57
|
this[kActivated] = false;
|
|
54
58
|
this[kStatus] = 'init';
|
|
59
|
+
this[kTracker] = new _Tracker.ActivityTracker(id);
|
|
55
60
|
this.executionId = undefined;
|
|
56
61
|
this[kMessageHandlers] = {
|
|
57
62
|
onActivityEvent: this._onActivityEvent.bind(this),
|
|
@@ -88,6 +93,11 @@ Object.defineProperty(ProcessExecution.prototype, 'isRunning', {
|
|
|
88
93
|
return this[kActivated];
|
|
89
94
|
}
|
|
90
95
|
});
|
|
96
|
+
Object.defineProperty(ProcessExecution.prototype, 'activityStatus', {
|
|
97
|
+
get() {
|
|
98
|
+
return this[kTracker].activityStatus;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
91
101
|
ProcessExecution.prototype.execute = function execute(executeMessage) {
|
|
92
102
|
if (!executeMessage) throw new Error('Process execution requires message');
|
|
93
103
|
if (!executeMessage.content || !executeMessage.content.executionId) throw new Error('Process execution requires execution id');
|
|
@@ -131,6 +141,7 @@ ProcessExecution.prototype.resume = function resume() {
|
|
|
131
141
|
if (this[kCompleted]) return;
|
|
132
142
|
const status = this.status;
|
|
133
143
|
if (status === 'init') return this._start();
|
|
144
|
+
const tracker = this[kTracker];
|
|
134
145
|
for (const msg of postponed.slice()) {
|
|
135
146
|
const activity = this.getActivityById(msg.content.id);
|
|
136
147
|
if (!activity) continue;
|
|
@@ -140,6 +151,7 @@ ProcessExecution.prototype.resume = function resume() {
|
|
|
140
151
|
msg.ack();
|
|
141
152
|
continue;
|
|
142
153
|
}
|
|
154
|
+
tracker.track(msg.fields.routingKey, msg);
|
|
143
155
|
activity.resume();
|
|
144
156
|
}
|
|
145
157
|
if (this[kCompleted]) return;
|
|
@@ -248,6 +260,17 @@ ProcessExecution.prototype.discard = function discard() {
|
|
|
248
260
|
type: 'discard'
|
|
249
261
|
});
|
|
250
262
|
};
|
|
263
|
+
ProcessExecution.prototype.cancel = function discard() {
|
|
264
|
+
return this[kActivityQ].queueMessage({
|
|
265
|
+
routingKey: 'execution.cancel'
|
|
266
|
+
}, {
|
|
267
|
+
id: this.id,
|
|
268
|
+
type: this.type,
|
|
269
|
+
executionId: this.executionId
|
|
270
|
+
}, {
|
|
271
|
+
type: 'cancel'
|
|
272
|
+
});
|
|
273
|
+
};
|
|
251
274
|
ProcessExecution.prototype.getState = function getState() {
|
|
252
275
|
const {
|
|
253
276
|
children,
|
|
@@ -285,6 +308,9 @@ ProcessExecution.prototype.getActivityById = function getActivityById(activityId
|
|
|
285
308
|
ProcessExecution.prototype.getSequenceFlows = function getSequenceFlows() {
|
|
286
309
|
return this[kElements].flows.slice();
|
|
287
310
|
};
|
|
311
|
+
ProcessExecution.prototype.getAssociations = function getAssociations() {
|
|
312
|
+
return this[kElements].associations.slice();
|
|
313
|
+
};
|
|
288
314
|
ProcessExecution.prototype.getApi = function getApi(message) {
|
|
289
315
|
if (!message) return (0, _Api.ProcessApi)(this.broker, this[kExecuteMessage]);
|
|
290
316
|
const content = message.content;
|
|
@@ -322,6 +348,7 @@ ProcessExecution.prototype._start = function start() {
|
|
|
322
348
|
for (const a of startActivities) a.shake();
|
|
323
349
|
}
|
|
324
350
|
for (const a of startActivities) a.init();
|
|
351
|
+
this[kStatus] = 'executing';
|
|
325
352
|
for (const a of startActivities) a.run();
|
|
326
353
|
postponed.splice(0);
|
|
327
354
|
detachedActivities.splice(0);
|
|
@@ -465,6 +492,7 @@ ProcessExecution.prototype._onActivityEvent = function onActivityEvent(routingKe
|
|
|
465
492
|
});
|
|
466
493
|
}
|
|
467
494
|
if (delegate) delegate = this._onDelegateEvent(message);
|
|
495
|
+
this[kTracker].track(routingKey, message);
|
|
468
496
|
this.broker.publish('event', routingKey, content, {
|
|
469
497
|
...message.properties,
|
|
470
498
|
delegate,
|
|
@@ -472,7 +500,6 @@ ProcessExecution.prototype._onActivityEvent = function onActivityEvent(routingKe
|
|
|
472
500
|
});
|
|
473
501
|
if (shaking) return this._onShookEnd(message);
|
|
474
502
|
if (!isDirectChild) return;
|
|
475
|
-
if (content.isAssociation) return;
|
|
476
503
|
switch (routingKey) {
|
|
477
504
|
case 'process.terminate':
|
|
478
505
|
return this[kActivityQ].queueMessage({
|
|
@@ -502,6 +529,17 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
502
529
|
case 'execution.discard':
|
|
503
530
|
message.ack();
|
|
504
531
|
return this._onDiscard(message);
|
|
532
|
+
case 'execution.discard.detached':
|
|
533
|
+
{
|
|
534
|
+
message.ack();
|
|
535
|
+
for (const detached of this[kElements].detachedActivities) {
|
|
536
|
+
this._getChildApi(detached).discard();
|
|
537
|
+
}
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
case 'execution.cancel':
|
|
541
|
+
message.ack();
|
|
542
|
+
return this._onCancel(message);
|
|
505
543
|
case 'activity.error.caught':
|
|
506
544
|
{
|
|
507
545
|
const prevMsg = this[kElements].postponed.find(msg => {
|
|
@@ -510,7 +548,6 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
510
548
|
if (!prevMsg) return message.ack();
|
|
511
549
|
break;
|
|
512
550
|
}
|
|
513
|
-
case 'activity.compensation.end':
|
|
514
551
|
case 'flow.looped':
|
|
515
552
|
case 'activity.leave':
|
|
516
553
|
return this._onChildCompleted(message);
|
|
@@ -522,14 +559,17 @@ ProcessExecution.prototype._onChildMessage = function onChildMessage(routingKey,
|
|
|
522
559
|
this[kElements].detachedActivities.push((0, _messageHelper.cloneMessage)(message));
|
|
523
560
|
break;
|
|
524
561
|
}
|
|
562
|
+
case 'activity.cancel':
|
|
563
|
+
{
|
|
564
|
+
if (this.isTransaction) this._onCancel(message);
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
525
567
|
case 'activity.discard':
|
|
526
|
-
case 'activity.compensation.start':
|
|
527
568
|
case 'activity.enter':
|
|
528
569
|
{
|
|
529
|
-
this[kStatus] = 'executing';
|
|
530
570
|
if (!content.inbound) break;
|
|
531
571
|
for (const inbound of content.inbound) {
|
|
532
|
-
if (!inbound.isSequenceFlow) continue;
|
|
572
|
+
if (!inbound.isSequenceFlow && !inbound.isAssociation) continue;
|
|
533
573
|
const inboundMessage = this._popPostponed(inbound);
|
|
534
574
|
if (inboundMessage) inboundMessage.ack();
|
|
535
575
|
}
|
|
@@ -567,7 +607,7 @@ ProcessExecution.prototype._popPostponed = function popPostponed(byContent) {
|
|
|
567
607
|
detachedActivities
|
|
568
608
|
} = this[kElements];
|
|
569
609
|
const postponedIdx = postponed.findIndex(msg => {
|
|
570
|
-
if (msg.content.isSequenceFlow) return msg.content.sequenceId === byContent.sequenceId;
|
|
610
|
+
if (msg.content.isSequenceFlow || msg.content.isAssociation) return msg.content.sequenceId === byContent.sequenceId;
|
|
571
611
|
return msg.content.executionId === byContent.executionId;
|
|
572
612
|
});
|
|
573
613
|
let postponedMsg;
|
|
@@ -598,9 +638,16 @@ ProcessExecution.prototype._onChildCompleted = function onChildCompleted(message
|
|
|
598
638
|
return this._complete('completed');
|
|
599
639
|
}
|
|
600
640
|
this._debug(`left <${id}> (${type}), pending runs ${postponedCount}, ${postponed.map(a => a.content.id).join(',')}`);
|
|
601
|
-
if (postponedCount === detachedActivities.length) {
|
|
602
|
-
|
|
603
|
-
|
|
641
|
+
if (postponedCount && postponedCount === detachedActivities.length) {
|
|
642
|
+
return this[kActivityQ].queueMessage({
|
|
643
|
+
routingKey: 'execution.discard.detached'
|
|
644
|
+
}, {
|
|
645
|
+
id: this.id,
|
|
646
|
+
type: this.type,
|
|
647
|
+
executionId: this.executionId
|
|
648
|
+
}, {
|
|
649
|
+
type: 'cancel'
|
|
650
|
+
});
|
|
604
651
|
}
|
|
605
652
|
if (isEnd && startActivities.length) {
|
|
606
653
|
const startSequences = this[kElements].startSequences;
|
|
@@ -637,33 +684,42 @@ ProcessExecution.prototype._onDiscard = function onDiscard() {
|
|
|
637
684
|
this._deactivate();
|
|
638
685
|
const running = this[kElements].postponed.splice(0);
|
|
639
686
|
this._debug(`discard process execution (discard child executions ${running.length})`);
|
|
640
|
-
|
|
641
|
-
|
|
687
|
+
if (this.isSubProcess) {
|
|
688
|
+
this.stop();
|
|
689
|
+
} else {
|
|
690
|
+
for (const flow of this.getSequenceFlows()) flow.stop();
|
|
691
|
+
for (const flow of this.getAssociations()) flow.stop();
|
|
692
|
+
for (const msg of running) this._getChildApi(msg).discard();
|
|
693
|
+
}
|
|
642
694
|
this[kActivityQ].purge();
|
|
643
695
|
return this._complete('discard');
|
|
644
696
|
};
|
|
645
|
-
ProcessExecution.prototype.
|
|
646
|
-
const
|
|
647
|
-
const
|
|
648
|
-
if (
|
|
649
|
-
|
|
650
|
-
this
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
697
|
+
ProcessExecution.prototype._onCancel = function onCancel() {
|
|
698
|
+
const running = this[kElements].postponed.slice(0);
|
|
699
|
+
const isTransaction = this.isTransaction;
|
|
700
|
+
if (isTransaction) {
|
|
701
|
+
this._debug(`cancel transaction execution (cancel child executions ${running.length})`);
|
|
702
|
+
this[kStatus] = 'cancel';
|
|
703
|
+
this.broker.publish('event', 'transaction.cancel', (0, _messageHelper.cloneMessage)(this[kExecuteMessage], {
|
|
704
|
+
state: 'cancel'
|
|
705
|
+
}));
|
|
706
|
+
for (const msg of running) {
|
|
707
|
+
if (msg.content.expect === 'compensate') {
|
|
708
|
+
this._getChildApi(msg).sendApiMessage('compensate');
|
|
709
|
+
} else if (!msg.content.isForCompensation) {
|
|
710
|
+
this._getChildApi(msg).discard();
|
|
656
711
|
}
|
|
657
|
-
}, {
|
|
658
|
-
consumerTag: `_ct-delegate-${correlationId}`,
|
|
659
|
-
noAck: true
|
|
660
|
-
});
|
|
661
|
-
for (const child of this[kElements].children) {
|
|
662
|
-
if (child.placeholder) continue;
|
|
663
|
-
child.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
|
|
664
|
-
if (consumed) break;
|
|
665
712
|
}
|
|
666
|
-
|
|
713
|
+
} else {
|
|
714
|
+
this._debug(`cancel process execution (cancel child executions ${running.length})`);
|
|
715
|
+
for (const msg of running) {
|
|
716
|
+
this._getChildApi(msg).discard();
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
ProcessExecution.prototype._onApiMessage = function onApiMessage(routingKey, message) {
|
|
721
|
+
if (message.properties.delegate) {
|
|
722
|
+
return this._delegateApiMessage(routingKey, message);
|
|
667
723
|
}
|
|
668
724
|
if (this.id !== message.content.id) {
|
|
669
725
|
const child = this.getActivityById(message.content.id);
|
|
@@ -672,6 +728,8 @@ ProcessExecution.prototype._onApiMessage = function onApiMessage(routingKey, mes
|
|
|
672
728
|
}
|
|
673
729
|
if (this.executionId !== message.content.executionId) return;
|
|
674
730
|
switch (message.properties.type) {
|
|
731
|
+
case 'cancel':
|
|
732
|
+
return this.cancel(message);
|
|
675
733
|
case 'discard':
|
|
676
734
|
return this.discard(message);
|
|
677
735
|
case 'stop':
|
|
@@ -683,11 +741,43 @@ ProcessExecution.prototype._onApiMessage = function onApiMessage(routingKey, mes
|
|
|
683
741
|
break;
|
|
684
742
|
}
|
|
685
743
|
};
|
|
744
|
+
ProcessExecution.prototype._delegateApiMessage = function delegateApiMessage(routingKey, message, continueOnConsumed) {
|
|
745
|
+
const correlationId = message.properties.correlationId || (0, _shared.getUniqueId)(this.executionId);
|
|
746
|
+
this._debug(`delegate api ${routingKey} message to children, with correlationId <${correlationId}>`);
|
|
747
|
+
const broker = this.broker;
|
|
748
|
+
let consumed = false;
|
|
749
|
+
broker.subscribeTmp('event', 'activity.consumed', (_, msg) => {
|
|
750
|
+
if (msg.properties.correlationId === correlationId) {
|
|
751
|
+
consumed = true;
|
|
752
|
+
this._debug(`delegated api message was consumed by ${msg.content ? msg.content.executionId : 'unknown'}`);
|
|
753
|
+
}
|
|
754
|
+
}, {
|
|
755
|
+
consumerTag: `_ct-delegate-${correlationId}`,
|
|
756
|
+
noAck: true
|
|
757
|
+
});
|
|
758
|
+
for (const child of this[kElements].children) {
|
|
759
|
+
if (child.placeholder) continue;
|
|
760
|
+
child.broker.publish('api', routingKey, (0, _messageHelper.cloneContent)(message.content), message.properties);
|
|
761
|
+
if (consumed && !continueOnConsumed) break;
|
|
762
|
+
}
|
|
763
|
+
return broker.cancel(`_ct-delegate-${correlationId}`);
|
|
764
|
+
};
|
|
686
765
|
ProcessExecution.prototype._complete = function complete(completionType, content) {
|
|
687
766
|
this._deactivate();
|
|
688
|
-
this._debug(`process execution ${completionType}`);
|
|
689
767
|
this[kCompleted] = true;
|
|
690
|
-
|
|
768
|
+
const status = this.status;
|
|
769
|
+
switch (this.status) {
|
|
770
|
+
case 'cancel':
|
|
771
|
+
this._debug('process execution cancelled');
|
|
772
|
+
case 'discard':
|
|
773
|
+
completionType = status;
|
|
774
|
+
break;
|
|
775
|
+
case 'terminated':
|
|
776
|
+
break;
|
|
777
|
+
default:
|
|
778
|
+
this._debug(`process execution ${completionType}`);
|
|
779
|
+
this[kStatus] = completionType;
|
|
780
|
+
}
|
|
691
781
|
const broker = this.broker;
|
|
692
782
|
this[kActivityQ].delete();
|
|
693
783
|
return broker.publish(this._exchangeName, `execution.${completionType}.${this.executionId}`, (0, _messageHelper.cloneContent)(this[kExecuteMessage].content, {
|
|
@@ -706,13 +796,15 @@ ProcessExecution.prototype._terminate = function terminate(message) {
|
|
|
706
796
|
this._debug('terminating process execution');
|
|
707
797
|
const running = this[kElements].postponed.splice(0);
|
|
708
798
|
for (const flow of this.getSequenceFlows()) flow.stop();
|
|
799
|
+
for (const flow of this.getAssociations()) flow.stop();
|
|
709
800
|
for (const msg of running) {
|
|
710
801
|
const {
|
|
711
802
|
id: postponedId,
|
|
712
|
-
isSequenceFlow
|
|
803
|
+
isSequenceFlow,
|
|
804
|
+
isAssociation
|
|
713
805
|
} = msg.content;
|
|
714
806
|
if (postponedId === message.content.id) continue;
|
|
715
|
-
if (isSequenceFlow) continue;
|
|
807
|
+
if (isSequenceFlow || isAssociation) continue;
|
|
716
808
|
this._getChildApi(msg).stop();
|
|
717
809
|
msg.ack();
|
|
718
810
|
}
|