bpmn-elements 8.1.0 → 8.2.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 CHANGED
@@ -1,6 +1,12 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ # 8.2.0
5
+
6
+ - fix resume when activity has formatting status, extensions were not re-activated
7
+ - fix InputOutputSpecification output now passed as dataOutput instead of dataInput, as it should
8
+ - refactor Extensions loading, bpmn io is now pushed to the end of the extensions list
9
+
4
10
  # 8.1.0
5
11
 
6
12
  - support non-interrupting BoundaryEvent with ISO8601 repeating interval timeCycle
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = Context;
7
7
 
8
+ var _BpmnIO = _interopRequireDefault(require("./io/BpmnIO"));
9
+
8
10
  var _Environment = _interopRequireDefault(require("./Environment"));
9
11
 
10
12
  var _ExtensionsMapper = _interopRequireDefault(require("./ExtensionsMapper"));
@@ -31,7 +33,7 @@ function ContextInstance(definitionContext, environment) {
31
33
  this.sid = sid;
32
34
  this.definitionContext = definitionContext;
33
35
  this.environment = environment;
34
- this.extensionsMapper = (0, _ExtensionsMapper.default)(this);
36
+ this.extensionsMapper = new _ExtensionsMapper.default(this);
35
37
  this.refs = {
36
38
  activityRefs: {},
37
39
  associationRefs: [],
@@ -204,5 +206,9 @@ proto.getStartActivities = function getStartActivities(filterOptions, scopeId) {
204
206
  };
205
207
 
206
208
  proto.loadExtensions = function loadExtensions(activity) {
207
- return this.extensionsMapper.get(activity);
209
+ const io = new _BpmnIO.default(activity, this);
210
+ const extensions = this.extensionsMapper.get(activity);
211
+ if (io.hasIo) extensions.extensions.push(io);
212
+ if (!extensions.extensions.length) return;
213
+ return extensions;
208
214
  };
@@ -4,50 +4,50 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = ExtensionsMapper;
7
+ const kActivated = Symbol.for('activated');
7
8
 
8
9
  function ExtensionsMapper(context) {
9
- const {
10
- extensions: envExtensions
11
- } = context.environment;
12
- const extensions = getExtensions();
13
- return {
14
- get
15
- };
16
-
17
- function get(activity) {
18
- const activityExtensions = extensions.reduce(applyExtension, []);
19
- return {
20
- activate,
21
- deactivate
22
- };
23
-
24
- function applyExtension(result, Extension) {
25
- const extension = Extension(activity, context);
26
- if (extension) result.push(extension);
27
- return result;
28
- }
29
-
30
- function activate(message) {
31
- for (const extension of activityExtensions) extension.activate(message);
32
- }
33
-
34
- function deactivate(message) {
35
- for (const extension of activityExtensions) extension.deactivate(message);
36
- }
37
- }
10
+ this.context = context;
11
+ }
38
12
 
39
- function getExtensions() {
40
- const result = [];
41
- if (!envExtensions) return result;
13
+ ExtensionsMapper.prototype.get = function get(activity) {
14
+ return new Extensions(activity, this.context, this._getExtensions());
15
+ };
42
16
 
43
- for (const key in envExtensions) {
44
- const extension = envExtensions[key];
17
+ ExtensionsMapper.prototype._getExtensions = function getExtensions() {
18
+ let extensions;
19
+ if (!(extensions = this.context.environment.extensions)) return [];
20
+ return Object.values(extensions);
21
+ };
45
22
 
46
- if (extension) {
47
- result.push(extension);
48
- }
49
- }
23
+ function Extensions(activity, context, extensions) {
24
+ const result = this.extensions = [];
50
25
 
51
- return result;
26
+ for (const Extension of extensions) {
27
+ const extension = Extension(activity, context);
28
+ if (extension) result.push(extension);
52
29
  }
53
- }
30
+
31
+ this[kActivated] = false;
32
+ }
33
+
34
+ Object.defineProperty(Extensions.prototype, 'count', {
35
+ get() {
36
+ return this.extensions.length;
37
+ }
38
+
39
+ });
40
+
41
+ Extensions.prototype.activate = function activate(message) {
42
+ if (this[kActivated]) return;
43
+ this[kActivated] = true;
44
+
45
+ for (const extension of this.extensions) extension.activate(message);
46
+ };
47
+
48
+ Extensions.prototype.deactivate = function deactivate(message) {
49
+ if (!this[kActivated]) return;
50
+ this[kActivated] = false;
51
+
52
+ for (const extension of this.extensions) extension.deactivate(message);
53
+ };
@@ -7,8 +7,6 @@ exports.default = void 0;
7
7
 
8
8
  var _ActivityExecution = _interopRequireDefault(require("./ActivityExecution"));
9
9
 
10
- var _BpmnIO = _interopRequireDefault(require("../io/BpmnIO"));
11
-
12
10
  var _shared = require("../shared");
13
11
 
14
12
  var _Api = require("../Api");
@@ -24,7 +22,6 @@ var _Errors = require("../error/Errors");
24
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
23
 
26
24
  const kActivityDef = Symbol.for('activityDefinition');
27
- const kBpmnIo = Symbol.for('bpmnIo');
28
25
  const kConsuming = Symbol.for('consuming');
29
26
  const kCounters = Symbol.for('counters');
30
27
  const kEventDefinitions = Symbol.for('eventDefinitions');
@@ -145,6 +142,7 @@ function Activity(Behaviour, activityDef, context) {
145
142
  }
146
143
 
147
144
  this[kEventDefinitions] = eventDefinitions && eventDefinitions.map(ed => new ed.Behaviour(this, ed, this.context));
145
+ this[kExtensions] = context.loadExtensions(this);
148
146
  }
149
147
 
150
148
  const proto = Activity.prototype;
@@ -173,23 +171,20 @@ Object.defineProperty(proto, 'executionId', {
173
171
  }
174
172
 
175
173
  });
176
- Object.defineProperty(proto, 'bpmnIo', {
174
+ Object.defineProperty(proto, 'extensions', {
177
175
  enumerable: true,
178
176
 
179
177
  get() {
180
- if (kBpmnIo in this) return this[kBpmnIo];
181
- const bpmnIo = this[kBpmnIo] = new _BpmnIO.default(this, this.context);
182
- return bpmnIo;
178
+ return this[kExtensions];
183
179
  }
184
180
 
185
181
  });
186
- Object.defineProperty(proto, 'extensions', {
182
+ Object.defineProperty(proto, 'bpmnIo', {
187
183
  enumerable: true,
188
184
 
189
185
  get() {
190
- if (kExtensions in this) return this[kExtensions];
191
- const extensions = this[kExtensions] = this.context.loadExtensions(this);
192
- return extensions;
186
+ const extensions = this[kExtensions];
187
+ return extensions && extensions.extensions.find(e => e.type === 'bpmnio');
193
188
  }
194
189
 
195
190
  });
@@ -485,10 +480,11 @@ proto._discardRun = function discardRun() {
485
480
 
486
481
  this._deactivateRunConsumers();
487
482
 
488
- if (this.extensions) this.extensions.deactivate();
483
+ const message = this[kStateMessage];
484
+ if (this.extensions) this.extensions.deactivate((0, _messageHelper.cloneMessage)(message));
489
485
  const broker = this.broker;
490
486
  broker.getQueue('run-q').purge();
491
- broker.publish('run', 'run.discard', (0, _messageHelper.cloneContent)(this[kStateMessage].content));
487
+ broker.publish('run', 'run.discard', (0, _messageHelper.cloneContent)(message.content));
492
488
 
493
489
  this._consumeRunQ();
494
490
  };
@@ -720,13 +716,13 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
720
716
 
721
717
  if (!isRedelivered) {
722
718
  this[kExec].execution = null;
719
+ if (this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(message));
720
+
721
+ this._publishEvent('enter', content, {
722
+ correlationId
723
+ });
723
724
  }
724
725
 
725
- if (this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(message), this);
726
- if (this.bpmnIo) this.bpmnIo.activate(message);
727
- if (!isRedelivered) this._publishEvent('enter', content, {
728
- correlationId
729
- });
730
726
  break;
731
727
  }
732
728
 
@@ -735,8 +731,7 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
735
731
  this.logger.debug(`<${id}> discard`, isRedelivered ? 'redelivered' : '');
736
732
  this.status = 'discard';
737
733
  this[kExec].execution = null;
738
- if (this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(message), this);
739
- if (this.bpmnIo) this.bpmnIo.activate(message);
734
+ if (this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(message));
740
735
 
741
736
  if (!isRedelivered) {
742
737
  this.broker.publish('run', 'run.discarded', content, {
@@ -781,28 +776,20 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
781
776
  {
782
777
  this.status = 'executing';
783
778
  this[kExecuteMessage] = message;
779
+ const exec = this[kExec];
780
+ if (isRedelivered && this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(message));
781
+ if (!exec.execution) exec.execution = new _ActivityExecution.default(this, this.context);
784
782
  this.broker.getQueue('execution-q').assertConsumer(this[kMessageHandlers].onExecutionMessage, {
785
783
  exclusive: true,
786
784
  consumerTag: '_activity-execution'
787
785
  });
788
- const exec = this[kExec];
789
- if (!exec.execution) exec.execution = new _ActivityExecution.default(this, this.context);
790
-
791
- if (isRedelivered) {
792
- return this._resumeExtensions(message, (err, formattedContent) => {
793
- if (err) return this.emitFatal(err, message.content);
794
- if (formattedContent) message.content = formattedContent;
795
- this.status = 'executing';
796
- return exec.execution.execute(message);
797
- });
798
- }
799
-
800
786
  return exec.execution.execute(message);
801
787
  }
802
788
 
803
789
  case 'run.end':
804
790
  {
805
- if (this.status === 'end') break;
791
+ this.logger.debug(`<${id}> end`, isRedelivered ? 'redelivered' : '');
792
+ if (isRedelivered) break;
806
793
  this[kCounters].taken++;
807
794
  this.status = 'end';
808
795
  return this._doRunLeave(message, false, () => {
@@ -860,8 +847,7 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
860
847
  case 'run.leave':
861
848
  {
862
849
  this.status = undefined;
863
- if (this.bpmnIo) this.bpmnIo.deactivate(message);
864
- if (this.extensions) this.extensions.deactivate(message);
850
+ if (this.extensions) this.extensions.deactivate((0, _messageHelper.cloneMessage)(message));
865
851
 
866
852
  if (!isRedelivered) {
867
853
  this.broker.publish('run', 'run.next', content, {
@@ -1044,9 +1030,8 @@ proto._doRunOutbound = function doRunOutbound(outboundList, content, discardSequ
1044
1030
  proto._onResumeMessage = function onResumeMessage(message) {
1045
1031
  message.ack();
1046
1032
  const stateMessage = this[kStateMessage];
1047
- const {
1048
- fields
1049
- } = stateMessage;
1033
+ const fields = stateMessage.fields;
1034
+ if (!fields.redelivered) return;
1050
1035
 
1051
1036
  switch (fields.routingKey) {
1052
1037
  case 'run.enter':
@@ -1060,7 +1045,7 @@ proto._onResumeMessage = function onResumeMessage(message) {
1060
1045
  return;
1061
1046
  }
1062
1047
 
1063
- if (!fields.redelivered) return;
1048
+ if (this.extensions) this.extensions.activate((0, _messageHelper.cloneMessage)(stateMessage));
1064
1049
  this.logger.debug(`<${this.id}> resume from ${message.content.status}`);
1065
1050
  return this.broker.publish('run', fields.routingKey, (0, _messageHelper.cloneContent)(stateMessage.content), stateMessage.properties);
1066
1051
  };
@@ -1087,7 +1072,7 @@ proto._onStop = function onStop(message) {
1087
1072
  broker.cancel('_format-consumer');
1088
1073
 
1089
1074
  if (running) {
1090
- if (this.extensions) this.extensions.deactivate(message || this._createMessage());
1075
+ if (this.extensions) this.extensions.deactivate(message ? (0, _messageHelper.cloneMessage)(message) : this._createMessage());
1091
1076
 
1092
1077
  this._publishEvent('stop', this._createMessage());
1093
1078
  }
@@ -1153,19 +1138,6 @@ proto._getOutboundSequenceFlowById = function getOutboundSequenceFlowById(flowId
1153
1138
  return this[kFlows].outboundSequenceFlows.find(flow => flow.id === flowId);
1154
1139
  };
1155
1140
 
1156
- proto._resumeExtensions = function resumeExtensions(message, callback) {
1157
- const extensions = this.extensions,
1158
- bpmnIo = this.bpmnIo;
1159
- if (!extensions && !bpmnIo) return callback();
1160
- if (extensions) extensions.activate((0, _messageHelper.cloneMessage)(message), this);
1161
- if (bpmnIo) bpmnIo.activate((0, _messageHelper.cloneMessage)(message), this);
1162
- this.status = 'formatting';
1163
- return this.formatter.format(message, (err, formattedContent, formatted) => {
1164
- if (err) return callback(err);
1165
- return callback(null, formatted && formattedContent);
1166
- });
1167
- };
1168
-
1169
1141
  proto._deactivateRunConsumers = function _deactivateRunConsumers() {
1170
1142
  const broker = this.broker;
1171
1143
  broker.cancel('_activity-api');
@@ -8,6 +8,7 @@ exports.default = BpmnIO;
8
8
  function BpmnIO(activity, context) {
9
9
  this.activity = activity;
10
10
  this.context = context;
11
+ this.type = 'bpmnio';
11
12
  const {
12
13
  ioSpecification: ioSpecificationDef,
13
14
  properties: propertiesDef
@@ -16,6 +17,13 @@ function BpmnIO(activity, context) {
16
17
  this.properties = propertiesDef && new propertiesDef.Behaviour(activity, propertiesDef, context);
17
18
  }
18
19
 
20
+ Object.defineProperty(BpmnIO.prototype, 'hasIo', {
21
+ get() {
22
+ return this.specification || this.properties;
23
+ }
24
+
25
+ });
26
+
19
27
  BpmnIO.prototype.activate = function activate(message) {
20
28
  const properties = this.properties,
21
29
  specification = this.specification;
@@ -29,8 +29,17 @@ function IoSpecification(activity, ioSpecificationDef, context) {
29
29
 
30
30
  const proto = IoSpecification.prototype;
31
31
 
32
- proto.activate = function activate() {
32
+ proto.activate = function activate(message) {
33
33
  if (this[kConsuming]) return;
34
+
35
+ if (message && message.fields.redelivered && message.fields.routingKey === 'run.start') {
36
+ this._onFormatEnter();
37
+ }
38
+
39
+ if (message && message.fields.redelivered && message.fields.routingKey === 'run.end') {
40
+ this._onFormatComplete(message);
41
+ }
42
+
34
43
  this[kConsuming] = this.broker.subscribeTmp('event', 'activity.#', this._onActivityEvent.bind(this), {
35
44
  noAck: true
36
45
  });
@@ -177,10 +186,11 @@ proto._onFormatComplete = function formatOnComplete(message) {
177
186
  const endRoutingKey = `run.onend.${safeType}.end`;
178
187
  broker.publish('format', `${startRoutingKey}.begin`, {
179
188
  endRoutingKey,
180
- ioSpecification: {
181
- dataInputs: sources.map(input => {
182
- return { ...input
183
- };
189
+ ioSpecification: { ...(messageInputs && {
190
+ dataInputs: messageInputs.map(input => {
191
+ return { ...input
192
+ };
193
+ })
184
194
  }),
185
195
  dataOutputs: this._getDataOutputs(dataOutputs)
186
196
  }
@@ -189,9 +199,13 @@ proto._onFormatComplete = function formatOnComplete(message) {
189
199
  for (const response of responses) sources[response.index].value = response.value;
190
200
 
191
201
  broker.publish('format', endRoutingKey, {
192
- ioSpecification: {
193
- dataInputs: sources,
194
- dataOutputs: this._getDataOutputs(dataOutputs)
202
+ ioSpecification: { ...(messageInputs && {
203
+ dataInputs: messageInputs.map(input => {
204
+ return { ...input
205
+ };
206
+ })
207
+ }),
208
+ dataOutputs: sources
195
209
  }
196
210
  });
197
211
  });
@@ -87,6 +87,10 @@ const proto = Properties.prototype;
87
87
  proto.activate = function activate(message) {
88
88
  if (this[kConsuming]) return;
89
89
 
90
+ if (message.fields.redelivered && message.fields.routingKey === 'run.start') {
91
+ this._onActivityEvent('activity.enter', message);
92
+ }
93
+
90
94
  if (message.fields.redelivered && message.content.properties) {
91
95
  this._onActivityEvent('activity.extension.resume', message);
92
96
  }
@@ -101,16 +105,13 @@ proto.deactivate = function deactivate() {
101
105
  };
102
106
 
103
107
  proto._onActivityEvent = function onActivityEvent(routingKey, message) {
104
- if (routingKey === 'activity.enter') {
105
- return this._formatOnEnter(message);
106
- }
107
-
108
- if (routingKey === 'activity.extension.resume') {
109
- return this._formatOnEnter(message);
110
- }
108
+ switch (routingKey) {
109
+ case 'activity.enter':
110
+ case 'activity.extension.resume':
111
+ return this._formatOnEnter(message);
111
112
 
112
- if (routingKey === 'activity.execution.completed') {
113
- return this._formatOnComplete(message);
113
+ case 'activity.execution.completed':
114
+ return this._formatOnComplete(message);
114
115
  }
115
116
  };
116
117
 
@@ -70,11 +70,7 @@ proto.execute = function execute(executeMessage) {
70
70
 
71
71
  proto.getService = function getService(message) {
72
72
  let Service = this.activity.behaviour.Service;
73
-
74
- if (!Service) {
75
- Service = this.environment.settings.enableDummyService ? DummyService : null;
76
- }
77
-
73
+ if (!Service && this.environment.settings.enableDummyService) Service = DummyService;
78
74
  return Service && new Service(this.activity, (0, _messageHelper.cloneMessage)(message));
79
75
  };
80
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmn-elements",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "Executable workflow elements based on BPMN 2.0",
5
5
  "main": "dist/index.js",
6
6
  "module": "index.js",
@@ -46,9 +46,9 @@
46
46
  ],
47
47
  "devDependencies": {
48
48
  "@aircall/expression-parser": "^1.0.4",
49
- "@babel/cli": "^7.18.6",
50
- "@babel/core": "^7.18.6",
51
- "@babel/preset-env": "^7.18.6",
49
+ "@babel/cli": "^7.19.3",
50
+ "@babel/core": "^7.19.3",
51
+ "@babel/preset-env": "^7.19.3",
52
52
  "@babel/register": "^7.18.6",
53
53
  "bpmn-moddle": "^7.1.2",
54
54
  "camunda-bpmn-moddle": "^6.1.2",
package/src/Context.js CHANGED
@@ -1,3 +1,4 @@
1
+ import BpmnIO from './io/BpmnIO';
1
2
  import Environment from './Environment';
2
3
  import ExtensionsMapper from './ExtensionsMapper';
3
4
  import {getUniqueId} from './shared';
@@ -16,7 +17,7 @@ function ContextInstance(definitionContext, environment) {
16
17
  this.sid = sid;
17
18
  this.definitionContext = definitionContext;
18
19
  this.environment = environment;
19
- this.extensionsMapper = ExtensionsMapper(this);
20
+ this.extensionsMapper = new ExtensionsMapper(this);
20
21
  this.refs = {
21
22
  activityRefs: {},
22
23
  associationRefs: [],
@@ -196,6 +197,10 @@ proto.getStartActivities = function getStartActivities(filterOptions, scopeId) {
196
197
  };
197
198
 
198
199
  proto.loadExtensions = function loadExtensions(activity) {
199
- return this.extensionsMapper.get(activity);
200
+ const io = new BpmnIO(activity, this);
201
+ const extensions = this.extensionsMapper.get(activity);
202
+ if (io.hasIo) extensions.extensions.push(io);
203
+ if (!extensions.extensions.length) return;
204
+ return extensions;
200
205
  };
201
206
 
@@ -1,42 +1,42 @@
1
- export default function ExtensionsMapper(context) {
2
- const {extensions: envExtensions} = context.environment;
3
- const extensions = getExtensions();
1
+ const kActivated = Symbol.for('activated');
4
2
 
5
- return {
6
- get,
7
- };
3
+ export default function ExtensionsMapper(context) {
4
+ this.context = context;
5
+ }
8
6
 
9
- function get(activity) {
10
- const activityExtensions = extensions.reduce(applyExtension, []);
11
- return {
12
- activate,
13
- deactivate,
14
- };
7
+ ExtensionsMapper.prototype.get = function get(activity) {
8
+ return new Extensions(activity, this.context, this._getExtensions());
9
+ };
15
10
 
16
- function applyExtension(result, Extension) {
17
- const extension = Extension(activity, context);
18
- if (extension) result.push(extension);
19
- return result;
20
- }
11
+ ExtensionsMapper.prototype._getExtensions = function getExtensions() {
12
+ let extensions;
13
+ if (!(extensions = this.context.environment.extensions)) return [];
14
+ return Object.values(extensions);
15
+ };
21
16
 
22
- function activate(message) {
23
- for (const extension of activityExtensions) extension.activate(message);
24
- }
25
- function deactivate(message) {
26
- for (const extension of activityExtensions) extension.deactivate(message);
27
- }
17
+ function Extensions(activity, context, extensions) {
18
+ const result = this.extensions = [];
19
+ for (const Extension of extensions) {
20
+ const extension = Extension(activity, context);
21
+ if (extension) result.push(extension);
28
22
  }
23
+ this[kActivated] = false;
24
+ }
29
25
 
30
- function getExtensions() {
31
- const result = [];
32
- if (!envExtensions) return result;
26
+ Object.defineProperty(Extensions.prototype, 'count', {
27
+ get() {
28
+ return this.extensions.length;
29
+ },
30
+ });
33
31
 
34
- for (const key in envExtensions) {
35
- const extension = envExtensions[key];
36
- if (extension) {
37
- result.push(extension);
38
- }
39
- }
40
- return result;
41
- }
42
- }
32
+ Extensions.prototype.activate = function activate(message) {
33
+ if (this[kActivated]) return;
34
+ this[kActivated] = true;
35
+ for (const extension of this.extensions) extension.activate(message);
36
+ };
37
+
38
+ Extensions.prototype.deactivate = function deactivate(message) {
39
+ if (!this[kActivated]) return;
40
+ this[kActivated] = false;
41
+ for (const extension of this.extensions) extension.deactivate(message);
42
+ };
@@ -1,5 +1,4 @@
1
1
  import ActivityExecution from './ActivityExecution';
2
- import BpmnIO from '../io/BpmnIO';
3
2
  import {brokerSafeId, getUniqueId} from '../shared';
4
3
  import {ActivityApi} from '../Api';
5
4
  import {ActivityBroker} from '../EventBroker';
@@ -8,7 +7,6 @@ import {cloneContent, cloneParent, cloneMessage} from '../messageHelper';
8
7
  import {makeErrorFromMessage, ActivityError} from '../error/Errors';
9
8
 
10
9
  const kActivityDef = Symbol.for('activityDefinition');
11
- const kBpmnIo = Symbol.for('bpmnIo');
12
10
  const kConsuming = Symbol.for('consuming');
13
11
  const kCounters = Symbol.for('counters');
14
12
  const kEventDefinitions = Symbol.for('eventDefinitions');
@@ -105,6 +103,7 @@ function Activity(Behaviour, activityDef, context) {
105
103
  }
106
104
 
107
105
  this[kEventDefinitions] = eventDefinitions && eventDefinitions.map((ed) => new ed.Behaviour(this, ed, this.context));
106
+ this[kExtensions] = context.loadExtensions(this);
108
107
  }
109
108
 
110
109
  const proto = Activity.prototype;
@@ -130,21 +129,18 @@ Object.defineProperty(proto, 'executionId', {
130
129
  },
131
130
  });
132
131
 
133
- Object.defineProperty(proto, 'bpmnIo', {
132
+ Object.defineProperty(proto, 'extensions', {
134
133
  enumerable: true,
135
134
  get() {
136
- if (kBpmnIo in this) return this[kBpmnIo];
137
- const bpmnIo = this[kBpmnIo] = new BpmnIO(this, this.context);
138
- return bpmnIo;
135
+ return this[kExtensions];
139
136
  },
140
137
  });
141
138
 
142
- Object.defineProperty(proto, 'extensions', {
139
+ Object.defineProperty(proto, 'bpmnIo', {
143
140
  enumerable: true,
144
141
  get() {
145
- if (kExtensions in this) return this[kExtensions];
146
- const extensions = this[kExtensions] = this.context.loadExtensions(this);
147
- return extensions;
142
+ const extensions = this[kExtensions];
143
+ return extensions && extensions.extensions.find(e => e.type === 'bpmnio');
148
144
  },
149
145
  });
150
146
 
@@ -408,10 +404,12 @@ proto._discardRun = function discardRun() {
408
404
  }
409
405
 
410
406
  this._deactivateRunConsumers();
411
- if (this.extensions) this.extensions.deactivate();
407
+
408
+ const message = this[kStateMessage];
409
+ if (this.extensions) this.extensions.deactivate(cloneMessage(message));
412
410
  const broker = this.broker;
413
411
  broker.getQueue('run-q').purge();
414
- broker.publish('run', 'run.discard', cloneContent(this[kStateMessage].content));
412
+ broker.publish('run', 'run.discard', cloneContent(message.content));
415
413
  this._consumeRunQ();
416
414
  };
417
415
 
@@ -601,12 +599,9 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
601
599
  this.status = 'entered';
602
600
  if (!isRedelivered) {
603
601
  this[kExec].execution = null;
602
+ if (this.extensions) this.extensions.activate(cloneMessage(message));
603
+ this._publishEvent('enter', content, {correlationId});
604
604
  }
605
-
606
- if (this.extensions) this.extensions.activate(cloneMessage(message), this);
607
- if (this.bpmnIo) this.bpmnIo.activate(message);
608
-
609
- if (!isRedelivered) this._publishEvent('enter', content, {correlationId});
610
605
  break;
611
606
  }
612
607
  case 'run.discard': {
@@ -615,8 +610,7 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
615
610
  this.status = 'discard';
616
611
  this[kExec].execution = null;
617
612
 
618
- if (this.extensions) this.extensions.activate(cloneMessage(message), this);
619
- if (this.bpmnIo) this.bpmnIo.activate(message);
613
+ if (this.extensions) this.extensions.activate(cloneMessage(message));
620
614
 
621
615
  if (!isRedelivered) {
622
616
  this.broker.publish('run', 'run.discarded', content, {correlationId});
@@ -631,7 +625,6 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
631
625
  this.broker.publish('run', 'run.execute', content, {correlationId});
632
626
  this._publishEvent('start', content, {correlationId});
633
627
  }
634
-
635
628
  break;
636
629
  }
637
630
  case 'run.execute.passthrough': {
@@ -645,23 +638,15 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
645
638
  this.status = 'executing';
646
639
  this[kExecuteMessage] = message;
647
640
 
648
- this.broker.getQueue('execution-q').assertConsumer(this[kMessageHandlers].onExecutionMessage, {exclusive: true, consumerTag: '_activity-execution'});
649
641
  const exec = this[kExec];
642
+ if (isRedelivered && this.extensions) this.extensions.activate(cloneMessage(message));
650
643
  if (!exec.execution) exec.execution = new ActivityExecution(this, this.context);
651
-
652
- if (isRedelivered) {
653
- return this._resumeExtensions(message, (err, formattedContent) => {
654
- if (err) return this.emitFatal(err, message.content);
655
- if (formattedContent) message.content = formattedContent;
656
- this.status = 'executing';
657
- return exec.execution.execute(message);
658
- });
659
- }
660
-
644
+ this.broker.getQueue('execution-q').assertConsumer(this[kMessageHandlers].onExecutionMessage, {exclusive: true, consumerTag: '_activity-execution'});
661
645
  return exec.execution.execute(message);
662
646
  }
663
647
  case 'run.end': {
664
- if (this.status === 'end') break;
648
+ this.logger.debug(`<${id}> end`, isRedelivered ? 'redelivered' : '');
649
+ if (isRedelivered) break;
665
650
 
666
651
  this[kCounters].taken++;
667
652
 
@@ -707,8 +692,7 @@ proto._continueRunMessage = function continueRunMessage(routingKey, message) {
707
692
  case 'run.leave': {
708
693
  this.status = undefined;
709
694
 
710
- if (this.bpmnIo) this.bpmnIo.deactivate(message);
711
- if (this.extensions) this.extensions.deactivate(message);
695
+ if (this.extensions) this.extensions.deactivate(cloneMessage(message));
712
696
 
713
697
  if (!isRedelivered) {
714
698
  this.broker.publish('run', 'run.next', content, {persistent: false});
@@ -844,7 +828,8 @@ proto._onResumeMessage = function onResumeMessage(message) {
844
828
  message.ack();
845
829
 
846
830
  const stateMessage = this[kStateMessage];
847
- const {fields} = stateMessage;
831
+ const fields = stateMessage.fields;
832
+ if (!fields.redelivered) return;
848
833
 
849
834
  switch (fields.routingKey) {
850
835
  case 'run.enter':
@@ -857,7 +842,7 @@ proto._onResumeMessage = function onResumeMessage(message) {
857
842
  return;
858
843
  }
859
844
 
860
- if (!fields.redelivered) return;
845
+ if (this.extensions) this.extensions.activate(cloneMessage(stateMessage));
861
846
 
862
847
  this.logger.debug(`<${this.id}> resume from ${message.content.status}`);
863
848
 
@@ -887,7 +872,7 @@ proto._onStop = function onStop(message) {
887
872
  broker.cancel('_format-consumer');
888
873
 
889
874
  if (running) {
890
- if (this.extensions) this.extensions.deactivate(message || this._createMessage());
875
+ if (this.extensions) this.extensions.deactivate(message ? cloneMessage(message) : this._createMessage());
891
876
  this._publishEvent('stop', this._createMessage());
892
877
  }
893
878
  };
@@ -936,20 +921,6 @@ proto._getOutboundSequenceFlowById = function getOutboundSequenceFlowById(flowId
936
921
  return this[kFlows].outboundSequenceFlows.find((flow) => flow.id === flowId);
937
922
  };
938
923
 
939
- proto._resumeExtensions = function resumeExtensions(message, callback) {
940
- const extensions = this.extensions, bpmnIo = this.bpmnIo;
941
- if (!extensions && !bpmnIo) return callback();
942
-
943
- if (extensions) extensions.activate(cloneMessage(message), this);
944
- if (bpmnIo) bpmnIo.activate(cloneMessage(message), this);
945
-
946
- this.status = 'formatting';
947
- return this.formatter.format(message, (err, formattedContent, formatted) => {
948
- if (err) return callback(err);
949
- return callback(null, formatted && formattedContent);
950
- });
951
- };
952
-
953
924
  proto._deactivateRunConsumers = function _deactivateRunConsumers() {
954
925
  const broker = this.broker;
955
926
  broker.cancel('_activity-api');
package/src/io/BpmnIO.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export default function BpmnIO(activity, context) {
2
2
  this.activity = activity;
3
3
  this.context = context;
4
+ this.type = 'bpmnio';
4
5
 
5
6
  const {
6
7
  ioSpecification: ioSpecificationDef,
@@ -11,6 +12,12 @@ export default function BpmnIO(activity, context) {
11
12
  this.properties = propertiesDef && new propertiesDef.Behaviour(activity, propertiesDef, context);
12
13
  }
13
14
 
15
+ Object.defineProperty(BpmnIO.prototype, 'hasIo', {
16
+ get() {
17
+ return this.specification || this.properties;
18
+ },
19
+ });
20
+
14
21
  BpmnIO.prototype.activate = function activate(message) {
15
22
  const properties = this.properties, specification = this.specification;
16
23
  if (properties) properties.activate(message);
@@ -9,6 +9,7 @@ export default function EnvironmentDataObject(dataObjectDef, {environment}) {
9
9
  }
10
10
 
11
11
  EnvironmentDataObject.prototype.read = function read(broker, exchange, routingKeyPrefix, messageProperties) {
12
+
12
13
  const environment = this.environment;
13
14
  const value = environment.variables._data && environment.variables._data[this.id];
14
15
  const content = this._createContent(value);
@@ -15,8 +15,14 @@ export default function IoSpecification(activity, ioSpecificationDef, context) {
15
15
 
16
16
  const proto = IoSpecification.prototype;
17
17
 
18
- proto.activate = function activate() {
18
+ proto.activate = function activate(message) {
19
19
  if (this[kConsuming]) return;
20
+ if (message && message.fields.redelivered && message.fields.routingKey === 'run.start') {
21
+ this._onFormatEnter();
22
+ }
23
+ if (message && message.fields.redelivered && message.fields.routingKey === 'run.end') {
24
+ this._onFormatComplete(message);
25
+ }
20
26
  this[kConsuming] = this.broker.subscribeTmp('event', 'activity.#', this._onActivityEvent.bind(this), {noAck: true});
21
27
  };
22
28
 
@@ -107,6 +113,7 @@ proto._onFormatComplete = function formatOnComplete(message) {
107
113
  const broker = this.broker;
108
114
  const context = this.context;
109
115
 
116
+
110
117
  const {dataObjects, sources} = dataOutputs.reduce((result, ioSource, index) => {
111
118
  const {value} = messageOutputs.find((output) => output.id === ioSource.id) || {};
112
119
  const source = {
@@ -117,7 +124,6 @@ proto._onFormatComplete = function formatOnComplete(message) {
117
124
  };
118
125
  result.sources.push(source);
119
126
 
120
-
121
127
  const dataObjectId = getPropertyValue(ioSource, 'behaviour.association.target.dataObject.id');
122
128
  if (!dataObjectId) return result;
123
129
  const dataObject = context.getDataObjectById(dataObjectId);
@@ -143,8 +149,10 @@ proto._onFormatComplete = function formatOnComplete(message) {
143
149
  broker.publish('format', `${startRoutingKey}.begin`, {
144
150
  endRoutingKey,
145
151
  ioSpecification: {
146
- dataInputs: sources.map((input) => {
147
- return {...input};
152
+ ...(messageInputs && {
153
+ dataInputs: messageInputs.map((input) => {
154
+ return {...input};
155
+ }),
148
156
  }),
149
157
  dataOutputs: this._getDataOutputs(dataOutputs),
150
158
  },
@@ -155,8 +163,12 @@ proto._onFormatComplete = function formatOnComplete(message) {
155
163
 
156
164
  broker.publish('format', endRoutingKey, {
157
165
  ioSpecification: {
158
- dataInputs: sources,
159
- dataOutputs: this._getDataOutputs(dataOutputs),
166
+ ...(messageInputs && {
167
+ dataInputs: messageInputs.map((input) => {
168
+ return {...input};
169
+ }),
170
+ }),
171
+ dataOutputs: sources,
160
172
  },
161
173
  });
162
174
  });
@@ -13,7 +13,6 @@ export default function Properties(activity, propertiesDef, context) {
13
13
  dataOutputObjects: [],
14
14
  };
15
15
 
16
-
17
16
  for (const {id, ...def} of propertiesDef.values) {
18
17
  const source = {
19
18
  id,
@@ -62,6 +61,9 @@ const proto = Properties.prototype;
62
61
 
63
62
  proto.activate = function activate(message) {
64
63
  if (this[kConsuming]) return;
64
+ if (message.fields.redelivered && message.fields.routingKey === 'run.start') {
65
+ this._onActivityEvent('activity.enter', message);
66
+ }
65
67
 
66
68
  if (message.fields.redelivered && message.content.properties) {
67
69
  this._onActivityEvent('activity.extension.resume', message);
@@ -75,16 +77,12 @@ proto.deactivate = function deactivate() {
75
77
  };
76
78
 
77
79
  proto._onActivityEvent = function onActivityEvent(routingKey, message) {
78
- if (routingKey === 'activity.enter') {
79
- return this._formatOnEnter(message);
80
- }
81
-
82
- if (routingKey === 'activity.extension.resume') {
83
- return this._formatOnEnter(message);
84
- }
85
-
86
- if (routingKey === 'activity.execution.completed') {
87
- return this._formatOnComplete(message);
80
+ switch (routingKey) {
81
+ case 'activity.enter':
82
+ case 'activity.extension.resume':
83
+ return this._formatOnEnter(message);
84
+ case 'activity.execution.completed':
85
+ return this._formatOnComplete(message);
88
86
  }
89
87
  };
90
88
 
@@ -46,9 +46,7 @@ proto.execute = function execute(executeMessage) {
46
46
 
47
47
  proto.getService = function getService(message) {
48
48
  let Service = this.activity.behaviour.Service;
49
- if (!Service) {
50
- Service = this.environment.settings.enableDummyService ? DummyService : null;
51
- }
49
+ if (!Service && this.environment.settings.enableDummyService) Service = DummyService;
52
50
  return Service && new Service(this.activity, cloneMessage(message));
53
51
  };
54
52