bpmn-elements 8.2.2 → 8.2.4

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 CHANGED
@@ -1,6 +1,11 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ # 8.2.3
5
+
6
+ - fix resumed boundary event initialized twice even if it's completed
7
+ - fix process lingering completed activities after resume
8
+
4
9
  # 8.2.2
5
10
 
6
11
  - mitigate possible stack overflow error by not acking message before publishing a new one. Fix after fix #31
@@ -15,7 +15,13 @@ function ActivityBroker(activity) {
15
15
  return executionBroker;
16
16
  }
17
17
  function ProcessBroker(owner) {
18
- return ExecutionBroker(owner, 'process');
18
+ const executionBroker = ExecutionBroker(owner, 'process');
19
+ executionBroker.broker.assertQueue('api-q', {
20
+ durable: false,
21
+ autoDelete: false
22
+ });
23
+ executionBroker.broker.bindQueue('api-q', 'api', '#');
24
+ return executionBroker;
19
25
  }
20
26
  function DefinitionBroker(owner, onBrokerReturn) {
21
27
  return ExecutionBroker(owner, 'definition', onBrokerReturn);
@@ -497,13 +497,16 @@ proto._onJoinInbound = function onJoinInbound(routingKey, message) {
497
497
  im.ack();
498
498
  return (0, _messageHelper.cloneContent)(im.content);
499
499
  });
500
- const discardSequence = !taken && evaluatedInbound.reduce((result, im) => {
501
- if (!im.content.discardSequence) return result;
502
- for (const sourceId of im.content.discardSequence) {
503
- if (result.indexOf(sourceId) === -1) result.push(sourceId);
500
+ let discardSequence;
501
+ if (!taken) {
502
+ discardSequence = [];
503
+ for (const im of evaluatedInbound) {
504
+ if (!im.content.discardSequence) continue;
505
+ for (const sourceId of im.content.discardSequence) {
506
+ if (discardSequence.indexOf(sourceId) === -1) discardSequence.push(sourceId);
507
+ }
504
508
  }
505
- return result;
506
- }, []);
509
+ }
507
510
  this.broker.cancel('_run-on-inbound');
508
511
  if (!taken) return this._runDiscard({
509
512
  inbound,
@@ -165,7 +165,7 @@ proto.recover = function recover(state) {
165
165
  } else {
166
166
  bp = this.getProcessById(bpid);
167
167
  }
168
- if (!bp) return;
168
+ if (!bp) continue;
169
169
  ids.push(bpid);
170
170
  bp.recover(bpState);
171
171
  running.push(bp);
@@ -114,7 +114,8 @@ proto._complete = function complete(message) {
114
114
  this._debug(executionId, `event definition ${type} completed, index ${index}`);
115
115
  const completeContent = (0, _messageHelper.cloneContent)(message.content, {
116
116
  executionId: this[kExecuteMessage].content.executionId,
117
- isRootScope: true
117
+ isRootScope: true,
118
+ isDefinitionScope: undefined
118
119
  });
119
120
  completeContent.parent = (0, _messageHelper.shiftParent)(parent);
120
121
  this.broker.publish('execution', this.completedRoutingKey, completeContent, {
@@ -49,9 +49,13 @@ proto.execute = function execute(executeMessage) {
49
49
  executionId
50
50
  } = executeMessage.content;
51
51
  const eventDefinitionExecution = this[kExecution];
52
- if (isRootScope) {
52
+ if (isRootScope && executeMessage.content.id === this.id) {
53
53
  this[kExecuteMessage] = executeMessage;
54
54
  const broker = this.broker;
55
+ if (executeMessage.fields.routingKey === 'execute.bound.completed') {
56
+ this._stop();
57
+ return broker.publish('execution', 'execute.completed', executeMessage.content, executeMessage.properties);
58
+ }
55
59
  const consumerTag = `_bound-listener-${executionId}`;
56
60
  this.attachedTo.broker.subscribeTmp('event', 'activity.leave', this._onAttachedLeave.bind(this), {
57
61
  noAck: true,
@@ -99,6 +103,7 @@ proto._onCompleted = function onCompleted(_, {
99
103
  if (!this.cancelActivity && !content.cancelActivity) {
100
104
  this._stop();
101
105
  return this.broker.publish('execution', 'execute.completed', (0, _messageHelper.cloneContent)(content, {
106
+ isDefinitionScope: false,
102
107
  cancelActivity: false
103
108
  }));
104
109
  }
@@ -130,23 +130,21 @@ proto.resume = function resume() {
130
130
  consumerTag: `_process-activity-${this.executionId}`
131
131
  });
132
132
  if (this[kCompleted]) return;
133
- switch (this.status) {
134
- case 'init':
135
- return this._start();
136
- case 'executing':
137
- {
138
- if (!postponed.length) return this._complete('completed');
139
- break;
140
- }
141
- }
142
- for (const {
143
- content
144
- } of postponed.slice()) {
145
- const activity = this.getActivityById(content.id);
133
+ const status = this.status;
134
+ if (status === 'init') return this._start();
135
+ for (const msg of postponed.slice()) {
136
+ const activity = this.getActivityById(msg.content.id);
146
137
  if (!activity) continue;
147
- if (content.placeholder) continue;
138
+ if (msg.content.placeholder) continue;
139
+ if (!activity.status) {
140
+ this._popPostponed(msg.content);
141
+ msg.ack();
142
+ continue;
143
+ }
148
144
  activity.resume();
149
145
  }
146
+ if (this[kCompleted]) return;
147
+ if (!postponed.length && status === 'executing') return this._complete('completed');
150
148
  };
151
149
  proto.recover = function recover(state) {
152
150
  if (!state) return this;
@@ -230,14 +228,14 @@ proto.stop = function stop() {
230
228
  this.getApi().stop();
231
229
  };
232
230
  proto.getPostponed = function getPostponed(filterFn) {
233
- return this[kElements].postponed.slice().reduce((result, msg) => {
231
+ const result = [];
232
+ for (const msg of this[kElements].postponed.slice()) {
234
233
  const api = this._getChildApi(msg);
235
- if (api) {
236
- if (filterFn && !filterFn(api)) return result;
237
- result.push(api);
238
- }
239
- return result;
240
- }, []);
234
+ if (!api) continue;
235
+ if (filterFn && !filterFn(api)) continue;
236
+ result.push(api);
237
+ }
238
+ return result;
241
239
  };
242
240
  proto.discard = function discard() {
243
241
  this[kStatus] = 'discard';
@@ -339,11 +337,19 @@ proto._activate = function activate() {
339
337
  onMessageFlowEvent,
340
338
  onActivityEvent
341
339
  } = this[kMessageHandlers];
342
- this.broker.subscribeTmp('api', '#', onApiMessage, {
343
- noAck: true,
344
- consumerTag: `_process-api-consumer-${this.executionId}`,
345
- priority: 200
346
- });
340
+ if (!this.isSubProcess) {
341
+ this.broker.consume('api-q', onApiMessage, {
342
+ noAck: true,
343
+ consumerTag: `_process-api-consumer-${this.executionId}`,
344
+ priority: 200
345
+ });
346
+ } else {
347
+ this.broker.subscribeTmp('api', '#', onApiMessage, {
348
+ noAck: true,
349
+ consumerTag: `_process-api-consumer-${this.executionId}`,
350
+ priority: 200
351
+ });
352
+ }
347
353
  const {
348
354
  outboundMessageFlows,
349
355
  flows,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmn-elements",
3
- "version": "8.2.2",
3
+ "version": "8.2.4",
4
4
  "description": "Executable workflow elements based on BPMN 2.0",
5
5
  "main": "dist/index.js",
6
6
  "module": "index.js",
@@ -47,16 +47,16 @@
47
47
  "devDependencies": {
48
48
  "@aircall/expression-parser": "^1.0.4",
49
49
  "@babel/cli": "^7.19.3",
50
- "@babel/core": "^7.20.2",
50
+ "@babel/core": "^7.20.5",
51
51
  "@babel/preset-env": "^7.20.2",
52
52
  "@babel/register": "^7.18.9",
53
53
  "bpmn-moddle": "^7.1.2",
54
54
  "camunda-bpmn-moddle": "^6.1.2",
55
55
  "chai": "^4.3.7",
56
- "chronokinesis": "^3.0.0",
56
+ "chronokinesis": "^4.0.1",
57
57
  "debug": "^4.3.4",
58
- "eslint": "^8.27.0",
59
- "got": "^11.8.5",
58
+ "eslint": "^8.29.0",
59
+ "got": "^11.8.6",
60
60
  "mocha": "^10.1.0",
61
61
  "mocha-cakes-2": "^3.3.0",
62
62
  "moddle-context-serializer": "^2.1.0",
@@ -15,7 +15,10 @@ function ActivityBroker(activity) {
15
15
  }
16
16
 
17
17
  function ProcessBroker(owner) {
18
- return ExecutionBroker(owner, 'process');
18
+ const executionBroker = ExecutionBroker(owner, 'process');
19
+ executionBroker.broker.assertQueue('api-q', {durable: false, autoDelete: false});
20
+ executionBroker.broker.bindQueue('api-q', 'api', '#');
21
+ return executionBroker;
19
22
  }
20
23
 
21
24
  function DefinitionBroker(owner, onBrokerReturn) {
@@ -499,13 +499,16 @@ proto._onJoinInbound = function onJoinInbound(routingKey, message) {
499
499
  return cloneContent(im.content);
500
500
  });
501
501
 
502
- const discardSequence = !taken && evaluatedInbound.reduce((result, im) => {
503
- if (!im.content.discardSequence) return result;
504
- for (const sourceId of im.content.discardSequence) {
505
- if (result.indexOf(sourceId) === -1) result.push(sourceId);
502
+ let discardSequence;
503
+ if (!taken) {
504
+ discardSequence = [];
505
+ for (const im of evaluatedInbound) {
506
+ if (!im.content.discardSequence) continue;
507
+ for (const sourceId of im.content.discardSequence) {
508
+ if (discardSequence.indexOf(sourceId) === -1) discardSequence.push(sourceId);
509
+ }
506
510
  }
507
- return result;
508
- }, []);
511
+ }
509
512
 
510
513
  this.broker.cancel('_run-on-inbound');
511
514
 
@@ -179,7 +179,7 @@ proto.recover = function recover(state) {
179
179
  } else {
180
180
  bp = this.getProcessById(bpid);
181
181
  }
182
- if (!bp) return;
182
+ if (!bp) continue;
183
183
 
184
184
  ids.push(bpid);
185
185
  bp.recover(bpState);
@@ -120,6 +120,7 @@ proto._complete = function complete(message) {
120
120
  const completeContent = cloneContent(message.content, {
121
121
  executionId: this[kExecuteMessage].content.executionId,
122
122
  isRootScope: true,
123
+ isDefinitionScope: undefined,
123
124
  });
124
125
  completeContent.parent = shiftParent(parent);
125
126
 
@@ -46,10 +46,15 @@ proto.execute = function execute(executeMessage) {
46
46
  const {isRootScope, executionId} = executeMessage.content;
47
47
 
48
48
  const eventDefinitionExecution = this[kExecution];
49
- if (isRootScope) {
49
+ if (isRootScope && executeMessage.content.id === this.id) {
50
50
  this[kExecuteMessage] = executeMessage;
51
51
 
52
52
  const broker = this.broker;
53
+ if (executeMessage.fields.routingKey === 'execute.bound.completed') {
54
+ this._stop();
55
+ return broker.publish('execution', 'execute.completed', executeMessage.content, executeMessage.properties);
56
+ }
57
+
53
58
  const consumerTag = `_bound-listener-${executionId}`;
54
59
  this.attachedTo.broker.subscribeTmp('event', 'activity.leave', this._onAttachedLeave.bind(this), {
55
60
  noAck: true,
@@ -95,7 +100,7 @@ proto._onExecutionMessage = function onExecutionMessage(routingKey, message) {
95
100
  proto._onCompleted = function onCompleted(_, {content}) {
96
101
  if (!this.cancelActivity && !content.cancelActivity) {
97
102
  this._stop();
98
- return this.broker.publish('execution', 'execute.completed', cloneContent(content, {cancelActivity: false}));
103
+ return this.broker.publish('execution', 'execute.completed', cloneContent(content, {isDefinitionScope: false, cancelActivity: false}));
99
104
  }
100
105
 
101
106
  this[kCompleteContent] = content;
@@ -138,21 +138,24 @@ proto.resume = function resume() {
138
138
 
139
139
  if (this[kCompleted]) return;
140
140
 
141
- switch (this.status) {
142
- case 'init':
143
- return this._start();
144
- case 'executing': {
145
- if (!postponed.length) return this._complete('completed');
146
- break;
147
- }
148
- }
141
+ const status = this.status;
142
+ if (status === 'init') return this._start();
149
143
 
150
- for (const {content} of postponed.slice()) {
151
- const activity = this.getActivityById(content.id);
144
+ for (const msg of postponed.slice()) {
145
+ const activity = this.getActivityById(msg.content.id);
152
146
  if (!activity) continue;
153
- if (content.placeholder) continue;
147
+ if (msg.content.placeholder) continue;
148
+ if (!activity.status) {
149
+ this._popPostponed(msg.content);
150
+ msg.ack();
151
+ continue;
152
+ }
154
153
  activity.resume();
155
154
  }
155
+
156
+ if (this[kCompleted]) return;
157
+
158
+ if (!postponed.length && status === 'executing') return this._complete('completed');
156
159
  };
157
160
 
158
161
  proto.recover = function recover(state) {
@@ -241,14 +244,14 @@ proto.stop = function stop() {
241
244
  };
242
245
 
243
246
  proto.getPostponed = function getPostponed(filterFn) {
244
- return this[kElements].postponed.slice().reduce((result, msg) => {
247
+ const result = [];
248
+ for (const msg of this[kElements].postponed.slice()) {
245
249
  const api = this._getChildApi(msg);
246
- if (api) {
247
- if (filterFn && !filterFn(api)) return result;
248
- result.push(api);
249
- }
250
- return result;
251
- }, []);
250
+ if (!api) continue;
251
+ if (filterFn && !filterFn(api)) continue;
252
+ result.push(api);
253
+ }
254
+ return result;
252
255
  };
253
256
 
254
257
  proto.discard = function discard() {
@@ -344,11 +347,19 @@ proto._start = function start() {
344
347
  proto._activate = function activate() {
345
348
  const {onApiMessage, onMessageFlowEvent, onActivityEvent} = this[kMessageHandlers];
346
349
 
347
- this.broker.subscribeTmp('api', '#', onApiMessage, {
348
- noAck: true,
349
- consumerTag: `_process-api-consumer-${this.executionId}`,
350
- priority: 200,
351
- });
350
+ if (!this.isSubProcess) {
351
+ this.broker.consume('api-q', onApiMessage, {
352
+ noAck: true,
353
+ consumerTag: `_process-api-consumer-${this.executionId}`,
354
+ priority: 200,
355
+ });
356
+ } else {
357
+ this.broker.subscribeTmp('api', '#', onApiMessage, {
358
+ noAck: true,
359
+ consumerTag: `_process-api-consumer-${this.executionId}`,
360
+ priority: 200,
361
+ });
362
+ }
352
363
 
353
364
  const {outboundMessageFlows, flows, associations, startActivities, triggeredByEvent, children} = this[kElements];
354
365