bpmn-elements 5.1.3 → 7.0.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +322 -0
  2. package/README.md +9 -3
  3. package/dist/index.js +71 -39
  4. package/dist/src/Api.js +77 -76
  5. package/dist/src/Context.js +169 -164
  6. package/dist/src/Environment.js +90 -102
  7. package/dist/src/EventBroker.js +89 -88
  8. package/dist/src/ExtensionsMapper.js +2 -2
  9. package/dist/src/MessageFormatter.js +164 -95
  10. package/dist/src/Scripts.js +6 -2
  11. package/dist/src/Timers.js +4 -6
  12. package/dist/src/activity/Activity.js +1108 -901
  13. package/dist/src/activity/ActivityExecution.js +342 -297
  14. package/dist/src/activity/Dummy.js +3 -3
  15. package/dist/src/definition/Definition.js +498 -444
  16. package/dist/src/definition/DefinitionExecution.js +722 -409
  17. package/dist/src/error/Errors.js +17 -7
  18. package/dist/src/eventDefinitions/CancelEventDefinition.js +190 -150
  19. package/dist/src/eventDefinitions/CompensateEventDefinition.js +194 -161
  20. package/dist/src/eventDefinitions/ConditionalEventDefinition.js +197 -135
  21. package/dist/src/eventDefinitions/ErrorEventDefinition.js +207 -165
  22. package/dist/src/eventDefinitions/EscalationEventDefinition.js +175 -141
  23. package/dist/src/eventDefinitions/EventDefinitionExecution.js +157 -129
  24. package/dist/src/eventDefinitions/LinkEventDefinition.js +174 -149
  25. package/dist/src/eventDefinitions/MessageEventDefinition.js +213 -176
  26. package/dist/src/eventDefinitions/SignalEventDefinition.js +203 -161
  27. package/dist/src/eventDefinitions/TerminateEventDefinition.js +21 -23
  28. package/dist/src/eventDefinitions/TimerEventDefinition.js +243 -228
  29. package/dist/src/events/BoundaryEvent.js +180 -144
  30. package/dist/src/events/EndEvent.js +18 -23
  31. package/dist/src/events/IntermediateCatchEvent.js +44 -58
  32. package/dist/src/events/IntermediateThrowEvent.js +18 -23
  33. package/dist/src/events/StartEvent.js +109 -94
  34. package/dist/src/flows/Association.js +94 -101
  35. package/dist/src/flows/MessageFlow.js +86 -103
  36. package/dist/src/flows/SequenceFlow.js +172 -184
  37. package/dist/src/gateways/EventBasedGateway.js +88 -84
  38. package/dist/src/gateways/ExclusiveGateway.js +13 -16
  39. package/dist/src/gateways/InclusiveGateway.js +11 -14
  40. package/dist/src/gateways/ParallelGateway.js +11 -14
  41. package/dist/src/getPropertyValue.js +34 -34
  42. package/dist/src/io/BpmnIO.js +31 -0
  43. package/dist/src/io/EnvironmentDataObject.js +33 -29
  44. package/dist/src/io/EnvironmentDataStore.js +52 -0
  45. package/dist/src/io/EnvironmentDataStoreReference.js +52 -0
  46. package/dist/src/io/InputOutputSpecification.js +177 -168
  47. package/dist/src/io/Properties.js +252 -0
  48. package/dist/src/messageHelper.js +1 -1
  49. package/dist/src/process/Process.js +433 -359
  50. package/dist/src/process/ProcessExecution.js +744 -645
  51. package/dist/src/shared.js +3 -6
  52. package/dist/src/tasks/CallActivity.js +160 -0
  53. package/dist/src/tasks/LoopCharacteristics.js +309 -330
  54. package/dist/src/tasks/ReceiveTask.js +233 -182
  55. package/dist/src/tasks/ScriptTask.js +35 -41
  56. package/dist/src/tasks/ServiceImplementation.js +13 -20
  57. package/dist/src/tasks/ServiceTask.js +82 -75
  58. package/dist/src/tasks/SignalTask.js +97 -93
  59. package/dist/src/tasks/StandardLoopCharacteristics.js +1 -1
  60. package/dist/src/tasks/SubProcess.js +195 -175
  61. package/dist/src/tasks/Task.js +17 -19
  62. package/index.js +8 -0
  63. package/package.json +16 -15
  64. package/src/Api.js +65 -59
  65. package/src/Context.js +142 -132
  66. package/src/Environment.js +88 -100
  67. package/src/EventBroker.js +67 -68
  68. package/src/ExtensionsMapper.js +2 -2
  69. package/src/MessageFormatter.js +132 -74
  70. package/src/Timers.js +4 -4
  71. package/src/activity/Activity.js +916 -757
  72. package/src/activity/ActivityExecution.js +293 -247
  73. package/src/activity/Dummy.js +2 -2
  74. package/src/definition/Definition.js +436 -401
  75. package/src/definition/DefinitionExecution.js +603 -343
  76. package/src/error/Errors.js +11 -6
  77. package/src/eventDefinitions/CancelEventDefinition.js +164 -121
  78. package/src/eventDefinitions/CompensateEventDefinition.js +158 -124
  79. package/src/eventDefinitions/ConditionalEventDefinition.js +147 -104
  80. package/src/eventDefinitions/ErrorEventDefinition.js +190 -131
  81. package/src/eventDefinitions/EscalationEventDefinition.js +139 -101
  82. package/src/eventDefinitions/EventDefinitionExecution.js +127 -95
  83. package/src/eventDefinitions/LinkEventDefinition.js +160 -129
  84. package/src/eventDefinitions/MessageEventDefinition.js +178 -121
  85. package/src/eventDefinitions/SignalEventDefinition.js +162 -106
  86. package/src/eventDefinitions/TerminateEventDefinition.js +19 -19
  87. package/src/eventDefinitions/TimerEventDefinition.js +202 -167
  88. package/src/events/BoundaryEvent.js +156 -115
  89. package/src/events/EndEvent.js +15 -18
  90. package/src/events/IntermediateCatchEvent.js +40 -44
  91. package/src/events/IntermediateThrowEvent.js +15 -18
  92. package/src/events/StartEvent.js +84 -50
  93. package/src/flows/Association.js +98 -113
  94. package/src/flows/MessageFlow.js +81 -97
  95. package/src/flows/SequenceFlow.js +145 -163
  96. package/src/gateways/EventBasedGateway.js +75 -68
  97. package/src/gateways/ExclusiveGateway.js +8 -13
  98. package/src/gateways/InclusiveGateway.js +8 -13
  99. package/src/gateways/ParallelGateway.js +8 -13
  100. package/src/getPropertyValue.js +34 -33
  101. package/src/io/BpmnIO.js +20 -0
  102. package/src/io/EnvironmentDataObject.js +29 -18
  103. package/src/io/EnvironmentDataStore.js +33 -0
  104. package/src/io/EnvironmentDataStoreReference.js +33 -0
  105. package/src/io/InputOutputSpecification.js +154 -157
  106. package/src/io/Properties.js +199 -0
  107. package/src/process/Process.js +374 -333
  108. package/src/process/ProcessExecution.js +606 -554
  109. package/src/shared.js +1 -5
  110. package/src/tasks/CallActivity.js +130 -0
  111. package/src/tasks/LoopCharacteristics.js +290 -289
  112. package/src/tasks/ReceiveTask.js +174 -107
  113. package/src/tasks/ScriptTask.js +27 -30
  114. package/src/tasks/ServiceImplementation.js +13 -18
  115. package/src/tasks/ServiceTask.js +67 -60
  116. package/src/tasks/SignalTask.js +77 -52
  117. package/src/tasks/StandardLoopCharacteristics.js +1 -1
  118. package/src/tasks/SubProcess.js +184 -157
  119. package/src/tasks/Task.js +15 -19
@@ -15,6 +15,8 @@ class ActivityError extends Error {
15
15
  }
16
16
  }
17
17
 
18
+ class RunError extends ActivityError {}
19
+
18
20
  class BpmnError extends Error {
19
21
  constructor(description, behaviour = {}, sourceMessage, inner) {
20
22
  const {errorCode} = behaviour;
@@ -33,6 +35,7 @@ class BpmnError extends Error {
33
35
  export {
34
36
  ActivityError,
35
37
  BpmnError,
38
+ RunError,
36
39
  makeErrorFromMessage
37
40
  };
38
41
 
@@ -41,21 +44,23 @@ function makeErrorFromMessage(errorMessage) {
41
44
  if (isKnownError(content)) return content;
42
45
 
43
46
  const {error} = content;
44
- if (!error) return;
47
+ if (!error) return new Error(`Malformatted error message with routing key ${errorMessage.fields && errorMessage.fields.routingKey}`);
45
48
 
46
49
  if (isKnownError(error)) return error;
47
50
  switch (error.type) {
48
51
  case 'ActivityError':
49
52
  return new ActivityError(error.message || error.description, error.source, error.inner ? error.inner : {code: error.code, name: error.name});
53
+ case 'RunError':
54
+ return new RunError(error.message || error.description, error.source, error.inner ? error.inner : {code: error.code, name: error.name});
50
55
  case 'BpmnError':
51
56
  return new BpmnError(error.message || error.description, error, error.source);
52
57
  }
53
58
 
54
59
  return error;
60
+ }
55
61
 
56
- function isKnownError(test) {
57
- if (test instanceof Error) return test;
58
- if (test instanceof ActivityError) return test;
59
- if (test instanceof BpmnError) return test;
60
- }
62
+ function isKnownError(test) {
63
+ if (test instanceof ActivityError) return test;
64
+ if (test instanceof BpmnError) return test;
65
+ if (test instanceof Error) return test;
61
66
  }
@@ -1,130 +1,173 @@
1
1
  import {brokerSafeId} from '../shared';
2
2
  import {cloneContent, shiftParent} from '../messageHelper';
3
3
 
4
+ const messageQSymbol = Symbol.for('cancelQ');
5
+ const completedSymbol = Symbol.for('completed');
6
+ const executeMessageSymbol = Symbol.for('executeMessage');
7
+
4
8
  export default function CancelEventDefinition(activity, eventDefinition) {
5
9
  const {id, broker, environment, isThrowing} = activity;
6
- const {type} = eventDefinition;
7
- const {debug} = environment.Logger(type.toLowerCase());
8
- const cancelQueueName = `cancel-${brokerSafeId(id)}-q`;
9
-
10
- if (!isThrowing) setupCatch();
11
-
12
- const source = {
13
- id,
14
- type,
15
- reference: {referenceType: 'cancel'},
16
- execute: isThrowing ? executeThrow : executeCatch,
17
- };
18
-
19
- return source;
20
-
21
- function executeCatch(executeMessage) {
22
- let completed;
23
-
24
- const messageContent = cloneContent(executeMessage.content);
25
- const {executionId, parent, attachedTo} = messageContent;
26
- const parentExecutionId = parent && parent.executionId;
27
-
28
- broker.consume(cancelQueueName, onCatchMessage, {noAck: true, consumerTag: `_oncancel-${executionId}`});
29
-
30
- if (completed) return;
31
-
32
- broker.subscribeTmp('api', `activity.#.${parentExecutionId}`, onApiMessage, {noAck: true, consumerTag: `_api-parent-${parentExecutionId}`});
33
- broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {noAck: true, consumerTag: `_api-${executionId}`});
34
-
35
- debug(`<${executionId} (${id})> expect cancel`);
36
-
37
- const exchangeKey = `execute.canceled.${executionId}`;
38
- broker.subscribeOnce('execution', exchangeKey, onCatchMessage, {consumerTag: `_onattached-cancel-${executionId}`});
39
- broker.publish('execution', 'execute.expect', cloneContent(messageContent, {
40
- pattern: '#.cancel',
41
- exchange: 'execution',
42
- exchangeKey,
43
- }));
44
-
45
- function onCatchMessage(_, message) {
46
- if (message.content && message.content.isTransaction) return onCancelTransaction(_, message);
47
-
48
- debug(`<${executionId} (${id})> cancel caught from <${message.content.id}>`);
49
- return complete(message.content.message);
50
- }
51
-
52
- function onCancelTransaction(_, message) {
53
- broker.cancel(`_oncancel-${executionId}`);
54
-
55
- debug(`<${executionId} (${id})> cancel transaction thrown by <${message.content.id}>`);
56
-
57
- broker.assertExchange('cancel', 'topic');
58
- broker.publish('execution', 'execute.detach', cloneContent(messageContent, {
59
- pattern: '#',
60
- bindExchange: 'cancel',
61
- sourceExchange: 'event',
62
- sourcePattern: '#',
63
- }));
64
-
65
- broker.publish('event', 'activity.compensate', cloneContent(message.content, {
66
- state: 'throw',
67
- }), {type: 'compensate', delegate: true});
68
-
69
- broker.subscribeTmp('cancel', 'activity.leave', (__, {content: msg}) => {
70
- if (msg.id !== attachedTo) return;
71
- return complete(message.content.message);
72
- }, {noAck: true, consumerTag: `_oncancelend-${executionId}`});
73
- }
74
-
75
- function complete(output) {
76
- completed = true;
77
- stop();
78
- debug(`<${executionId} (${id})> completed`);
79
- return broker.publish('execution', 'execute.completed', {...messageContent, output, state: 'cancel'});
80
- }
10
+ const type = eventDefinition.type;
11
+
12
+ this.id = id;
13
+ this.type = type;
14
+ const reference = this.reference = {referenceType: 'cancel'};
15
+ this.isThrowing = isThrowing;
16
+ this.activity = activity;
17
+ this.environment = environment;
18
+ this.broker = broker;
19
+ this.logger = environment.Logger(type.toLowerCase());
20
+
21
+ if (!isThrowing) {
22
+ this[completedSymbol] = false;
23
+ const messageQueueName = `${reference.referenceType}-${brokerSafeId(id)}-q`;
24
+ this[messageQSymbol] = broker.assertQueue(messageQueueName, {autoDelete: false, durable: true});
25
+ broker.bindQueue(messageQueueName, 'api', `*.${reference.referenceType}.#`, {durable: true, priority: 400});
26
+ }
27
+ }
81
28
 
82
- function onApiMessage(routingKey, message) {
83
- const messageType = message.properties.type;
84
- switch (messageType) {
85
- case 'discard': {
86
- completed = true;
87
- stop();
88
- return broker.publish('execution', 'execute.discard', {...messageContent});
89
- }
90
- case 'stop': {
91
- stop();
92
- break;
93
- }
94
- }
29
+ const proto = CancelEventDefinition.prototype;
30
+
31
+ Object.defineProperty(proto, 'executionId', {
32
+ get() {
33
+ const message = this[executeMessageSymbol];
34
+ return message && message.content.executionId;
35
+ },
36
+ });
37
+
38
+ proto.execute = function execute(executeMessage) {
39
+ return this.isThrowing ? this.executeThrow(executeMessage) : this.executeCatch(executeMessage);
40
+ };
41
+
42
+ proto.executeCatch = function executeCatch(executeMessage) {
43
+ this[executeMessageSymbol] = executeMessage;
44
+ this[completedSymbol] = false;
45
+
46
+ const executeContent = executeMessage.content;
47
+ const {executionId, parent} = executeContent;
48
+ const parentExecutionId = parent.executionId;
49
+
50
+ const broker = this.broker;
51
+ const onCatchMessage = this._onCatchMessage.bind(this);
52
+ this[messageQSymbol].consume(onCatchMessage, {
53
+ noAck: true,
54
+ consumerTag: `_oncancel-${executionId}`,
55
+ });
56
+
57
+ if (this[completedSymbol]) return;
58
+
59
+ const onApiMessage = this._onApiMessage.bind(this);
60
+ broker.subscribeTmp('api', `activity.#.${parentExecutionId}`, onApiMessage, {
61
+ noAck: true,
62
+ consumerTag: `_api-parent-${executionId}`,
63
+ });
64
+ broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {
65
+ noAck: true,
66
+ consumerTag: `_api-${executionId}`,
67
+ });
68
+
69
+ this._debug('expect cancel');
70
+
71
+ const exchangeKey = `execute.canceled.${executionId}`;
72
+ broker.subscribeOnce('execution', exchangeKey, onCatchMessage, {
73
+ consumerTag: `_onattached-cancel-${executionId}`,
74
+ });
75
+
76
+ broker.publish('execution', 'execute.expect', cloneContent(executeContent, {
77
+ pattern: '#.cancel',
78
+ exchange: 'execution',
79
+ exchangeKey,
80
+ }));
81
+ };
82
+
83
+ proto.executeThrow = function executeThrow(executeMessage) {
84
+ const {isTransaction} = this.environment.variables.content || {};
85
+ const executeContent = executeMessage.content;
86
+ const {executionId, parent} = executeContent;
87
+
88
+ this.logger.debug(`<${executionId} (${this.activity.id})> throw cancel${isTransaction ? ' transaction' : ''}`);
89
+
90
+ const broker = this.broker;
91
+ const cancelContent = cloneContent(executeContent, {
92
+ isTransaction,
93
+ executionId: parent.executionId,
94
+ state: 'throw',
95
+ });
96
+ cancelContent.parent = shiftParent(parent);
97
+
98
+ broker.publish('event', 'activity.cancel', cancelContent, {type: 'cancel', delegate: isTransaction});
99
+
100
+ return broker.publish('execution', 'execute.completed', cloneContent(executeContent));
101
+ };
102
+
103
+ proto._onCatchMessage = function onCatchMessage(_, message) {
104
+ if (message.content && message.content.isTransaction) return this._onCancelTransaction(_, message);
105
+
106
+ this._debug(`cancel caught from <${message.content.id}>`);
107
+ return this._complete(message.content.message);
108
+ };
109
+
110
+ proto._onCancelTransaction = function onCancelTransaction(_, message) {
111
+ const broker = this.broker, executionId = this.executionId;
112
+ const executeContent = this[executeMessageSymbol].content;
113
+ broker.cancel(`_oncancel-${executionId}`);
114
+
115
+ this._debug(`cancel transaction thrown by <${message.content.id}>`);
116
+
117
+ broker.assertExchange('cancel', 'topic');
118
+ broker.publish('execution', 'execute.detach', cloneContent(executeContent, {
119
+ pattern: '#',
120
+ bindExchange: 'cancel',
121
+ sourceExchange: 'event',
122
+ sourcePattern: '#',
123
+ }));
124
+
125
+ broker.publish('event', 'activity.compensate', cloneContent(message.content, {
126
+ state: 'throw',
127
+ }), {type: 'compensate', delegate: true});
128
+
129
+ broker.subscribeTmp('cancel', 'activity.leave', (__, {content: msg}) => {
130
+ if (msg.id !== executeContent.attachedTo) return;
131
+ return this._complete(message.content.message);
132
+ }, {noAck: true, consumerTag: `_oncancelend-${executionId}`});
133
+ };
134
+
135
+ proto._complete = function complete(output) {
136
+ this[completedSymbol] = true;
137
+ this._stop();
138
+ this._debug('completed');
139
+ const content = cloneContent(this[executeMessageSymbol].content, {
140
+ output,
141
+ state: 'cancel',
142
+ });
143
+ return this.broker.publish('execution', 'execute.completed', content);
144
+ };
145
+
146
+ proto._onApiMessage = function onApiMessage(routingKey, message) {
147
+ switch (message.properties.type) {
148
+ case 'discard': {
149
+ this[completedSymbol] = true;
150
+ this._stop();
151
+ const content = cloneContent(this[executeMessageSymbol].content);
152
+ return this.broker.publish('execution', 'execute.discard', content);
95
153
  }
96
-
97
- function stop() {
98
- broker.cancel(`_api-parent-${parentExecutionId}`);
99
- broker.cancel(`_api-${executionId}`);
100
- broker.cancel(`_oncancel-${executionId}`);
101
- broker.cancel(`_oncancelend-${executionId}`);
102
- broker.cancel(`_onattached-cancel-${executionId}`);
103
- broker.purgeQueue(cancelQueueName);
154
+ case 'stop': {
155
+ this._stop();
156
+ break;
104
157
  }
105
158
  }
106
-
107
- function executeThrow(executeMessage) {
108
- const {isTransaction} = environment.variables.content || {};
109
- const messageContent = cloneContent(executeMessage.content);
110
- const {executionId, parent} = messageContent;
111
- const parentExecutionId = parent && parent.executionId;
112
-
113
- debug(`<${executionId} (${id})> throw cancel${isTransaction ? ' transaction' : ''}`);
114
-
115
- broker.publish('event', 'activity.cancel', {
116
- ...cloneContent(messageContent),
117
- isTransaction,
118
- executionId: parentExecutionId,
119
- parent: shiftParent(parent),
120
- state: 'throw',
121
- }, {type: 'cancel', delegate: isTransaction});
122
-
123
- return broker.publish('execution', 'execute.completed', {...messageContent});
124
- }
125
-
126
- function setupCatch() {
127
- broker.assertQueue(cancelQueueName, {autoDelete: false, durable: true});
128
- broker.bindQueue(cancelQueueName, 'api', '*.cancel.#', {durable: true, priority: 400});
129
- }
130
- }
159
+ };
160
+
161
+ proto._stop = function stop() {
162
+ const broker = this.broker, executionId = this.executionId;
163
+ broker.cancel(`_api-parent-${executionId}`);
164
+ broker.cancel(`_api-${executionId}`);
165
+ broker.cancel(`_oncancel-${executionId}`);
166
+ broker.cancel(`_oncancelend-${executionId}`);
167
+ broker.cancel(`_onattached-cancel-${executionId}`);
168
+ this[messageQSymbol].purge();
169
+ };
170
+
171
+ proto._debug = function debug(msg) {
172
+ this.logger.debug(`<${this.executionId} (${this.activity.id})> ${msg}`);
173
+ };
@@ -1,144 +1,178 @@
1
1
  import {brokerSafeId} from '../shared';
2
2
  import {cloneContent, cloneMessage, shiftParent} from '../messageHelper';
3
3
 
4
- export default function CompensationEventDefinition(activity, eventDefinition, context) {
5
- const {id, broker, environment, isThrowing} = activity;
6
- const {type} = eventDefinition;
7
- const {debug} = environment.Logger(type.toLowerCase());
8
- const compensationQueueName = `compensate-${brokerSafeId(id)}-q`;
9
- const associations = context.getOutboundAssociations(id) || [];
10
-
11
- if (!isThrowing) setupCatch();
12
-
13
- const source = {
14
- id,
15
- type,
16
- reference: {referenceType: 'compensate'},
17
- execute: isThrowing ? executeThrow : executeCatch,
18
- };
19
-
20
- return source;
21
-
22
- function executeCatch(executeMessage) {
23
- let completed;
24
-
25
- const messageContent = cloneContent(executeMessage.content);
26
- const {executionId, parent} = messageContent;
27
- const parentExecutionId = parent && parent.executionId;
28
-
29
- broker.consume(compensationQueueName, onCompensateApiMessage, {noAck: true, consumerTag: `_oncompensate-${executionId}`});
4
+ const completedSymbol = Symbol.for('completed');
5
+ const executeMessageSymbol = Symbol.for('executeMessage');
6
+ const messageQSymbol = Symbol.for('messageQ');
7
+ const compensateQSymbol = Symbol.for('compensateQ');
8
+ const associationsSymbol = Symbol.for('associations');
30
9
 
31
- if (completed) return;
32
-
33
- broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {noAck: true, consumerTag: `_api-${executionId}`});
10
+ export default function CompensateEventDefinition(activity, eventDefinition, context) {
11
+ const {id, broker, environment, isThrowing} = activity;
34
12
 
35
- if (completed) return stop();
13
+ this.id = id;
14
+ const type = this.type = eventDefinition.type;
15
+ const reference = this.reference = {referenceType: 'compensate'};
16
+ this.isThrowing = isThrowing;
17
+ this.activity = activity;
18
+ this.broker = broker;
19
+ this.logger = environment.Logger(type.toLowerCase());
20
+
21
+ if (!isThrowing) {
22
+ this[completedSymbol] = false;
23
+ this[associationsSymbol] = context.getOutboundAssociations(id) || [];
24
+ const messageQueueName = `${reference.referenceType}-${brokerSafeId(id)}-q`;
25
+ this[messageQSymbol] = broker.assertQueue(messageQueueName, {autoDelete: false, durable: true});
26
+ broker.bindQueue(messageQueueName, 'api', `*.${reference.referenceType}.#`, {durable: true, priority: 400});
27
+ }
28
+ }
36
29
 
37
- debug(`<${executionId} (${id})> expect compensate`);
30
+ const proto = CompensateEventDefinition.prototype;
31
+
32
+ Object.defineProperty(proto, 'executionId', {
33
+ get() {
34
+ const message = this[executeMessageSymbol];
35
+ return message && message.content.executionId;
36
+ },
37
+ });
38
+
39
+ proto.execute = function execute(executeMessage) {
40
+ return this.isThrowing ? this.executeThrow(executeMessage) : this.executeCatch(executeMessage);
41
+ };
42
+
43
+ proto.executeCatch = function executeCatch(executeMessage) {
44
+ this[executeMessageSymbol] = executeMessage;
45
+ this[completedSymbol] = false;
46
+
47
+ const executeContent = executeMessage.content;
48
+ const {executionId, parent} = executeContent;
49
+
50
+ this._debug('expect compensate');
51
+
52
+ const broker = this.broker;
53
+ broker.assertExchange('compensate', 'topic');
54
+ this[compensateQSymbol] = broker.assertQueue('compensate-q', {durable: true, autoDelete: false});
55
+ broker.subscribeTmp('compensate', 'execute.#', this._onCollect.bind(this), {
56
+ noAck: true,
57
+ consumerTag: '_oncollect-messages',
58
+ });
59
+
60
+ broker.publish('execution', 'execute.detach', cloneContent(executeContent, {
61
+ sourceExchange: 'execution',
62
+ bindExchange: 'compensate',
63
+ }));
64
+
65
+ this[messageQSymbol].consume(this._onCompensateApiMessage.bind(this), {
66
+ noAck: true,
67
+ consumerTag: `_oncompensate-${executionId}`,
68
+ });
69
+
70
+ if (this[completedSymbol]) return;
71
+
72
+ const onApiMessage = this._onApiMessage.bind(this);
73
+ broker.subscribeTmp('api', `activity.#.${executionId}`, onApiMessage, {
74
+ noAck: true,
75
+ consumerTag: `_api-${executionId}`,
76
+ });
77
+
78
+ const detachContent = cloneContent(executeContent, {
79
+ executionId: parent.executionId,
80
+ bindExchange: 'compensate',
81
+ });
82
+ detachContent.parent = shiftParent(parent);
83
+
84
+ broker.publish('event', 'activity.detach', detachContent);
85
+ };
86
+
87
+ proto.executeThrow = function executeThrow(executeMessage) {
88
+ const executeContent = executeMessage.content;
89
+ const {executionId, parent} = executeContent;
90
+ const parentExecutionId = parent && parent.executionId;
91
+
92
+ this.logger.debug(`<${executionId} (${this.activity.id})> throw compensate`);
93
+
94
+ const broker = this.broker;
95
+ const throwContent = cloneContent(executeContent, {
96
+ executionId: parentExecutionId,
97
+ state: 'throw',
98
+ });
99
+ throwContent.parent = shiftParent(parent);
100
+ broker.publish('event', 'activity.compensate', throwContent, {type: 'compensate', delegate: true});
101
+
102
+ return broker.publish('execution', 'execute.completed', cloneContent(executeContent));
103
+ };
104
+
105
+ proto._onCollect = function onCollect(routingKey, message) {
106
+ switch (routingKey) {
107
+ case 'execute.error':
108
+ case 'execute.completed': {
109
+ return this[compensateQSymbol].queueMessage(message.fields, cloneContent(message.content), message.properties);
110
+ }
111
+ }
112
+ };
38
113
 
39
- broker.assertExchange('compensate', 'topic');
40
- const compensateQ = broker.assertQueue('compensate-q', {durable: true, autoDelete: false});
41
- broker.subscribeTmp('compensate', 'execute.#', onCollect, {noAck: true, consumerTag: '_oncollect-messages'});
42
- broker.publish('execution', 'execute.detach', cloneContent(messageContent, {bindExchange: 'compensate'}));
114
+ proto._onCompensateApiMessage = function onCompensateApiMessage(routingKey, message) {
115
+ const output = message.content.message;
116
+ this[completedSymbol] = true;
43
117
 
44
- broker.publish('event', 'activity.detach', {
45
- ...messageContent,
46
- executionId: parentExecutionId,
47
- parent: shiftParent(parent),
48
- bindExchange: 'compensate',
49
- });
118
+ this._stop();
50
119
 
51
- function onCollect(routingKey, message) {
52
- switch (routingKey) {
53
- case 'execute.error':
54
- case 'execute.completed': {
55
- return compensateQ.queueMessage(message.fields, cloneContent(message.content), message.properties);
56
- }
57
- }
58
- }
120
+ this._debug('caught compensate event');
121
+ const broker = this.broker;
122
+ const executeContent = this[executeMessageSymbol].content;
123
+ const catchContent = cloneContent(executeContent, {
124
+ message: {...output},
125
+ executionId: executeContent.parent.executionId,
126
+ });
127
+ catchContent.parent = shiftParent(catchContent.parent);
59
128
 
60
- function onCompensateApiMessage(routingKey, message) {
61
- const output = message.content.message;
62
- completed = true;
129
+ broker.publish('event', 'activity.catch', catchContent, {type: 'catch'});
63
130
 
64
- stop();
131
+ const compensateQ = this[compensateQSymbol];
132
+ compensateQ.on('depleted', onDepleted);
133
+ compensateQ.consume(this._onCollected.bind(this), {noAck: true, consumerTag: '_convey-messages'});
65
134
 
66
- debug(`<${executionId} (${id})> caught compensate event`);
67
- broker.publish('event', 'activity.catch', {
68
- ...messageContent,
69
- message: {...output},
70
- executionId: parentExecutionId,
71
- parent: shiftParent(executeMessage.content.parent),
72
- }, {type: 'catch'});
135
+ for (const association of this[associationsSymbol]) association.complete(cloneMessage(message));
73
136
 
74
- compensateQ.on('depleted', onDepleted);
75
- compensateQ.consume(onCollected, {noAck: true, consumerTag: '_convey-messages'});
137
+ function onDepleted() {
138
+ compensateQ.off('depleted', onDepleted);
139
+ return broker.publish('execution', 'execute.completed', cloneContent(executeContent, {output, state: 'catch'}));
140
+ }
141
+ };
76
142
 
77
- associations.forEach((association) => {
78
- association.complete(cloneMessage(message));
79
- });
143
+ proto._onCollected = function onCollected(routingKey, message) {
144
+ for (const association of this[associationsSymbol]) association.take(cloneMessage(message));
145
+ };
80
146
 
81
- function onDepleted() {
82
- compensateQ.off('depleted', onDepleted);
83
- return broker.publish('execution', 'execute.completed', {...messageContent, output, state: 'catch'});
84
- }
85
- }
147
+ proto._onApiMessage = function onApiMessage(routingKey, message) {
148
+ const messageType = message.properties.type;
86
149
 
87
- function onCollected(routingKey, message) {
88
- associations.forEach((association) => {
89
- association.take(cloneMessage(message));
90
- });
150
+ switch (messageType) {
151
+ case 'compensate': {
152
+ return this._onCompensateApiMessage(routingKey, message);
91
153
  }
92
-
93
- function onApiMessage(routingKey, message) {
94
- const messageType = message.properties.type;
95
-
96
- switch (messageType) {
97
- case 'compensate': {
98
- return onCompensateApiMessage(routingKey, message);
99
- }
100
- case 'discard': {
101
- completed = true;
102
- stop();
103
- associations.forEach((association) => {
104
- association.discard(cloneMessage(message));
105
- });
106
- return broker.publish('execution', 'execute.discard', {...messageContent});
107
- }
108
- case 'stop': {
109
- stop();
110
- break;
111
- }
112
- }
154
+ case 'discard': {
155
+ this[completedSymbol] = true;
156
+ this._stop();
157
+ for (const association of this[associationsSymbol]) association.discard(cloneMessage(message));
158
+ return this.broker.publish('execution', 'execute.discard', cloneContent(this[executeMessageSymbol].content));
113
159
  }
114
-
115
- function stop() {
116
- broker.cancel(`_api-${executionId}`);
117
- broker.cancel(`_oncompensate-${executionId}`);
118
- broker.cancel('_oncollect-messages');
119
- broker.cancel('_convey-messages');
160
+ case 'stop': {
161
+ this._stop();
162
+ break;
120
163
  }
121
164
  }
122
-
123
- function executeThrow(executeMessage) {
124
- const messageContent = cloneContent(executeMessage.content);
125
- const {executionId, parent} = messageContent;
126
- const parentExecutionId = parent && parent.executionId;
127
-
128
- debug(`<${executionId} (${id})> throw compensate`);
129
-
130
- broker.publish('event', 'activity.compensate', {
131
- ...cloneContent(messageContent),
132
- executionId: parentExecutionId,
133
- parent: shiftParent(parent),
134
- state: 'throw',
135
- }, {type: 'compensate', delegate: true});
136
-
137
- return broker.publish('execution', 'execute.completed', {...messageContent});
138
- }
139
-
140
- function setupCatch() {
141
- broker.assertQueue(compensationQueueName, {autoDelete: false, durable: true});
142
- broker.bindQueue(compensationQueueName, 'api', '*.compensate.#', {durable: true, priority: 400});
143
- }
144
- }
165
+ };
166
+
167
+ proto._stop = function stop() {
168
+ const broker = this.broker, executionId = this.executionId;
169
+ broker.cancel(`_api-${executionId}`);
170
+ broker.cancel(`_oncompensate-${executionId}`);
171
+ broker.cancel('_oncollect-messages');
172
+ broker.cancel('_convey-messages');
173
+ this[messageQSymbol].purge();
174
+ };
175
+
176
+ proto._debug = function debug(msg) {
177
+ this.logger.debug(`<${this.executionId} (${this.activity.id})> ${msg}`);
178
+ };