@onlineapps/conn-orch-orchestrator 1.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.
- package/API.md +195 -0
- package/README.md +585 -0
- package/jest.config.js +29 -0
- package/jest.setup.js +38 -0
- package/package.json +41 -0
- package/src/WorkflowOrchestrator.js +341 -0
- package/src/index.js +43 -0
- package/test/component/orchestrator.component.test.js +378 -0
- package/test/integration/orchestrator.integration.test.js +313 -0
- package/test/unit/WorkflowOrchestrator.test.js +253 -0
package/README.md
ADDED
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
<a name="module_@onlineapps/conn-orch-orchestrator"></a>
|
|
2
|
+
|
|
3
|
+
## @onlineapps/conn-orch-orchestrator
|
|
4
|
+
Workflow orchestration coordinator managing complete workflow execution.
|
|
5
|
+
Provides centralized control flow handling, step routing, and workflow state management
|
|
6
|
+
for OA Drive microservices.
|
|
7
|
+
|
|
8
|
+
**See**: [GitHub Repository](https://github.com/onlineapps/oa-drive/tree/main/shared/connector/conn-orch-orchestrator)
|
|
9
|
+
**Since**: 1.0.0
|
|
10
|
+
**Author**: OA Drive Team
|
|
11
|
+
**License**: MIT
|
|
12
|
+
|
|
13
|
+
* [@onlineapps/conn-orch-orchestrator](#module_@onlineapps/conn-orch-orchestrator)
|
|
14
|
+
* _static_
|
|
15
|
+
* [.VERSION](#module_@onlineapps/conn-orch-orchestrator.VERSION) : <code>string</code>
|
|
16
|
+
* _inner_
|
|
17
|
+
* [~OrchestratorConnector](#module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector)
|
|
18
|
+
* [new OrchestratorConnector()](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
19
|
+
* [new OrchestratorConnector(config)](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
20
|
+
* [~OrchestratorConnector](#module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector)
|
|
21
|
+
* [new OrchestratorConnector()](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
22
|
+
* [new OrchestratorConnector(config)](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
23
|
+
* [~processWorkflowMessage(message)](#module_@onlineapps/conn-orch-orchestrator..processWorkflowMessage) ⇒ <code>Promise.<WorkflowResult></code> \| <code>boolean</code> \| <code>string</code> \| <code>number</code>
|
|
24
|
+
* [~processStep(message)](#module_@onlineapps/conn-orch-orchestrator..processStep) ⇒ <code>Promise.<\*></code>
|
|
25
|
+
* [~handleControlFlow(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleControlFlow) ⇒ <code>Promise.<\*></code>
|
|
26
|
+
* [~handleIfStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleIfStep) ⇒ <code>Promise.<\*></code>
|
|
27
|
+
* [~handleForeachStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleForeachStep) ⇒ <code>Promise.<Array></code>
|
|
28
|
+
* [~handleForkJoinStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleForkJoinStep) ⇒ <code>Promise.<\*></code>
|
|
29
|
+
* [~handleSwitchStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleSwitchStep) ⇒ <code>Promise.<\*></code>
|
|
30
|
+
* [~routeToNextService(message, nextService, stepResult, nextIndex)](#module_@onlineapps/conn-orch-orchestrator..routeToNextService) ⇒ <code>Promise.<void></code>
|
|
31
|
+
* [~completeWorkflow(message, finalResult)](#module_@onlineapps/conn-orch-orchestrator..completeWorkflow) ⇒ <code>Promise.<void></code>
|
|
32
|
+
* [~handleWorkflowFailure(message, error)](#module_@onlineapps/conn-orch-orchestrator..handleWorkflowFailure) ⇒ <code>Promise.<void></code>
|
|
33
|
+
* [~getStats()](#module_@onlineapps/conn-orch-orchestrator..getStats) ⇒ <code>OrchestratorStats</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code>
|
|
34
|
+
* [~resetStats()](#module_@onlineapps/conn-orch-orchestrator..resetStats) ⇒ <code>void</code>
|
|
35
|
+
* [~create(config)](#module_@onlineapps/conn-orch-orchestrator..create) ⇒ <code>OrchestratorConnector</code>
|
|
36
|
+
* [~WorkflowMessage](#module_@onlineapps/conn-orch-orchestrator..WorkflowMessage) : <code>Object</code>
|
|
37
|
+
* [~WorkflowResult](#module_@onlineapps/conn-orch-orchestrator..WorkflowResult) : <code>Object</code>
|
|
38
|
+
* [~ControlFlowStep](#module_@onlineapps/conn-orch-orchestrator..ControlFlowStep) : <code>Object</code>
|
|
39
|
+
* [~OrchestratorStats](#module_@onlineapps/conn-orch-orchestrator..OrchestratorStats) : <code>Object</code>
|
|
40
|
+
|
|
41
|
+
<a name="module_@onlineapps/conn-orch-orchestrator.VERSION"></a>
|
|
42
|
+
|
|
43
|
+
### @onlineapps/conn-orch-orchestrator.VERSION : <code>string</code>
|
|
44
|
+
Current version
|
|
45
|
+
|
|
46
|
+
**Kind**: static constant of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
47
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector"></a>
|
|
48
|
+
|
|
49
|
+
### @onlineapps/conn-orch-orchestrator~OrchestratorConnector
|
|
50
|
+
**Kind**: inner class of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
51
|
+
|
|
52
|
+
* [~OrchestratorConnector](#module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector)
|
|
53
|
+
* [new OrchestratorConnector()](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
54
|
+
* [new OrchestratorConnector(config)](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
55
|
+
|
|
56
|
+
<a name="new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new"></a>
|
|
57
|
+
|
|
58
|
+
#### new OrchestratorConnector()
|
|
59
|
+
Workflow orchestration connector managing complete workflow execution
|
|
60
|
+
|
|
61
|
+
**Example** *(Basic Usage)*
|
|
62
|
+
```js
|
|
63
|
+
const orchestrator = new OrchestratorConnector({
|
|
64
|
+
mqClient: mqConnector,
|
|
65
|
+
cookbook: cookbookConnector,
|
|
66
|
+
apiMapper: apiMapperConnector,
|
|
67
|
+
serviceName: 'invoice-service'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await orchestrator.processWorkflowMessage(message);
|
|
71
|
+
```
|
|
72
|
+
**Example** *(With Caching)*
|
|
73
|
+
```js
|
|
74
|
+
const orchestrator = new OrchestratorConnector({
|
|
75
|
+
mqClient: mqConnector,
|
|
76
|
+
cookbook: cookbookConnector,
|
|
77
|
+
apiMapper: apiMapperConnector,
|
|
78
|
+
cache: cacheConnector,
|
|
79
|
+
serviceName: 'invoice-service',
|
|
80
|
+
defaultTimeout: 60000
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
<a name="new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new"></a>
|
|
84
|
+
|
|
85
|
+
#### new OrchestratorConnector(config)
|
|
86
|
+
Creates a new OrchestratorConnector instance
|
|
87
|
+
|
|
88
|
+
**Throws**:
|
|
89
|
+
|
|
90
|
+
- <code>TypeError</code> If required dependencies are missing
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
| Param | Type | Default | Description |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| config | <code>Object</code> | | Configuration object |
|
|
96
|
+
| config.mqClient | <code>Object</code> | | MQ client connector for message routing |
|
|
97
|
+
| config.cookbook | <code>Object</code> | | Cookbook connector for workflow parsing |
|
|
98
|
+
| [config.apiMapper] | <code>Object</code> | | API mapper for HTTP calls |
|
|
99
|
+
| [config.cache] | <code>Object</code> | | Cache connector for step caching |
|
|
100
|
+
| [config.logger] | <code>Object</code> | <code>console</code> | Logger instance |
|
|
101
|
+
| [config.serviceName] | <code>string</code> | <code>"'unknown'"</code> | Service name for tracing |
|
|
102
|
+
| [config.defaultTimeout] | <code>number</code> | <code>30000</code> | Default timeout in ms |
|
|
103
|
+
| [config.maxStepRetries] | <code>number</code> | <code>3</code> | Maximum retries per step |
|
|
104
|
+
|
|
105
|
+
**Example** *(Full Configuration)*
|
|
106
|
+
```js
|
|
107
|
+
const orchestrator = new OrchestratorConnector({
|
|
108
|
+
mqClient: mqConnector,
|
|
109
|
+
cookbook: cookbookConnector,
|
|
110
|
+
apiMapper: apiMapperConnector,
|
|
111
|
+
cache: cacheConnector,
|
|
112
|
+
logger: loggerConnector,
|
|
113
|
+
serviceName: 'invoice-service',
|
|
114
|
+
defaultTimeout: 60000,
|
|
115
|
+
maxStepRetries: 5
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector"></a>
|
|
119
|
+
|
|
120
|
+
### @onlineapps/conn-orch-orchestrator~OrchestratorConnector
|
|
121
|
+
**Kind**: inner class of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
122
|
+
|
|
123
|
+
* [~OrchestratorConnector](#module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector)
|
|
124
|
+
* [new OrchestratorConnector()](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
125
|
+
* [new OrchestratorConnector(config)](#new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new)
|
|
126
|
+
|
|
127
|
+
<a name="new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new"></a>
|
|
128
|
+
|
|
129
|
+
#### new OrchestratorConnector()
|
|
130
|
+
Workflow orchestration connector managing complete workflow execution
|
|
131
|
+
|
|
132
|
+
**Example** *(Basic Usage)*
|
|
133
|
+
```js
|
|
134
|
+
const orchestrator = new OrchestratorConnector({
|
|
135
|
+
mqClient: mqConnector,
|
|
136
|
+
cookbook: cookbookConnector,
|
|
137
|
+
apiMapper: apiMapperConnector,
|
|
138
|
+
serviceName: 'invoice-service'
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
await orchestrator.processWorkflowMessage(message);
|
|
142
|
+
```
|
|
143
|
+
**Example** *(With Caching)*
|
|
144
|
+
```js
|
|
145
|
+
const orchestrator = new OrchestratorConnector({
|
|
146
|
+
mqClient: mqConnector,
|
|
147
|
+
cookbook: cookbookConnector,
|
|
148
|
+
apiMapper: apiMapperConnector,
|
|
149
|
+
cache: cacheConnector,
|
|
150
|
+
serviceName: 'invoice-service',
|
|
151
|
+
defaultTimeout: 60000
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
<a name="new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new"></a>
|
|
155
|
+
|
|
156
|
+
#### new OrchestratorConnector(config)
|
|
157
|
+
Creates a new OrchestratorConnector instance
|
|
158
|
+
|
|
159
|
+
**Throws**:
|
|
160
|
+
|
|
161
|
+
- <code>TypeError</code> If required dependencies are missing
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
| Param | Type | Default | Description |
|
|
165
|
+
| --- | --- | --- | --- |
|
|
166
|
+
| config | <code>Object</code> | | Configuration object |
|
|
167
|
+
| config.mqClient | <code>Object</code> | | MQ client connector for message routing |
|
|
168
|
+
| config.cookbook | <code>Object</code> | | Cookbook connector for workflow parsing |
|
|
169
|
+
| [config.apiMapper] | <code>Object</code> | | API mapper for HTTP calls |
|
|
170
|
+
| [config.cache] | <code>Object</code> | | Cache connector for step caching |
|
|
171
|
+
| [config.logger] | <code>Object</code> | <code>console</code> | Logger instance |
|
|
172
|
+
| [config.serviceName] | <code>string</code> | <code>"'unknown'"</code> | Service name for tracing |
|
|
173
|
+
| [config.defaultTimeout] | <code>number</code> | <code>30000</code> | Default timeout in ms |
|
|
174
|
+
| [config.maxStepRetries] | <code>number</code> | <code>3</code> | Maximum retries per step |
|
|
175
|
+
|
|
176
|
+
**Example** *(Full Configuration)*
|
|
177
|
+
```js
|
|
178
|
+
const orchestrator = new OrchestratorConnector({
|
|
179
|
+
mqClient: mqConnector,
|
|
180
|
+
cookbook: cookbookConnector,
|
|
181
|
+
apiMapper: apiMapperConnector,
|
|
182
|
+
cache: cacheConnector,
|
|
183
|
+
logger: loggerConnector,
|
|
184
|
+
serviceName: 'invoice-service',
|
|
185
|
+
defaultTimeout: 60000,
|
|
186
|
+
maxStepRetries: 5
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..processWorkflowMessage"></a>
|
|
190
|
+
|
|
191
|
+
### @onlineapps/conn-orch-orchestrator~processWorkflowMessage(message) ⇒ <code>Promise.<WorkflowResult></code> \| <code>boolean</code> \| <code>string</code> \| <code>number</code>
|
|
192
|
+
Process workflow message - main entry point
|
|
193
|
+
|
|
194
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
195
|
+
**Returns**: <code>Promise.<WorkflowResult></code> - Processing result<code>boolean</code> - result.success - Whether processing succeeded<code>string</code> - result.workflowId - Workflow ID<code>number</code> - result.duration - Processing duration in ms
|
|
196
|
+
**Throws**:
|
|
197
|
+
|
|
198
|
+
- <code>Error</code> If cookbook validation fails
|
|
199
|
+
- <code>Error</code> If step processing fails
|
|
200
|
+
|
|
201
|
+
**Emits**: [<code>completed</code>](#OrchestratorConnector+workflow.event_completed), [<code>failed</code>](#OrchestratorConnector+workflow.event_failed)
|
|
202
|
+
|
|
203
|
+
| Param | Type | Default | Description |
|
|
204
|
+
| --- | --- | --- | --- |
|
|
205
|
+
| message | <code>WorkflowMessage</code> | | Workflow message to process |
|
|
206
|
+
| [message.workflow_id] | <code>string</code> | | Unique workflow ID |
|
|
207
|
+
| message.cookbook | <code>Object</code> | | Cookbook definition |
|
|
208
|
+
| [message.current_step] | <code>number</code> | <code>0</code> | Current step index |
|
|
209
|
+
| [message.context] | <code>Object</code> | <code>{}</code> | Workflow context data |
|
|
210
|
+
| [message.trace] | <code>Array</code> | <code>[]</code> | Execution trace |
|
|
211
|
+
|
|
212
|
+
**Example** *(Process Workflow)*
|
|
213
|
+
```js
|
|
214
|
+
const result = await orchestrator.processWorkflowMessage({
|
|
215
|
+
workflow_id: 'wf-123',
|
|
216
|
+
cookbook: cookbookDef,
|
|
217
|
+
current_step: 0,
|
|
218
|
+
context: { invoice_id: 'inv-456' }
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (result.success) {
|
|
222
|
+
console.log(`Workflow completed in ${result.duration}ms`);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
**Example** *(With Error Handling)*
|
|
226
|
+
```js
|
|
227
|
+
try {
|
|
228
|
+
await orchestrator.processWorkflowMessage(message);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error('Workflow failed:', error);
|
|
231
|
+
// Message sent to DLQ automatically
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..processStep"></a>
|
|
235
|
+
|
|
236
|
+
### @onlineapps/conn-orch-orchestrator~processStep(message) ⇒ <code>Promise.<\*></code>
|
|
237
|
+
Process single workflow step
|
|
238
|
+
|
|
239
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
240
|
+
**Returns**: <code>Promise.<\*></code> - Step execution result
|
|
241
|
+
**Throws**:
|
|
242
|
+
|
|
243
|
+
- <code>Error</code> If step not found in cookbook
|
|
244
|
+
- <code>Error</code> If API call fails and onError is not 'continue'
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
| Param | Type | Description |
|
|
248
|
+
| --- | --- | --- |
|
|
249
|
+
| message | <code>WorkflowMessage</code> | Workflow message with step info |
|
|
250
|
+
|
|
251
|
+
**Example** *(Process Regular Step)*
|
|
252
|
+
```js
|
|
253
|
+
const result = await orchestrator.processStep({
|
|
254
|
+
cookbook: cookbook,
|
|
255
|
+
current_step: 2,
|
|
256
|
+
context: { data: 'value' }
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
**Example** *(Process Control Flow Step)*
|
|
260
|
+
```js
|
|
261
|
+
const result = await orchestrator.processStep({
|
|
262
|
+
cookbook: { steps: [{ type: 'foreach', items: [...] }] },
|
|
263
|
+
current_step: 0
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleControlFlow"></a>
|
|
267
|
+
|
|
268
|
+
### @onlineapps/conn-orch-orchestrator~handleControlFlow(step, message) ⇒ <code>Promise.<\*></code>
|
|
269
|
+
Handle control flow steps (if, foreach, fork_join, switch)
|
|
270
|
+
|
|
271
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
272
|
+
**Returns**: <code>Promise.<\*></code> - Control flow execution result
|
|
273
|
+
**Throws**:
|
|
274
|
+
|
|
275
|
+
- <code>Error</code> If unknown control flow type
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
| Param | Type | Description |
|
|
279
|
+
| --- | --- | --- |
|
|
280
|
+
| step | <code>ControlFlowStep</code> | Control flow step definition |
|
|
281
|
+
| step.type | <code>string</code> | Type: 'if', 'foreach', 'fork_join', 'switch' |
|
|
282
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
283
|
+
|
|
284
|
+
**Example** *(If/Else Flow)*
|
|
285
|
+
```js
|
|
286
|
+
await orchestrator.handleControlFlow({
|
|
287
|
+
type: 'if',
|
|
288
|
+
condition: '${amount} > 1000',
|
|
289
|
+
then: { service: 'approval', operation: 'request' },
|
|
290
|
+
else: { service: 'payment', operation: 'process' }
|
|
291
|
+
}, message);
|
|
292
|
+
```
|
|
293
|
+
**Example** *(Foreach Iteration)*
|
|
294
|
+
```js
|
|
295
|
+
await orchestrator.handleControlFlow({
|
|
296
|
+
type: 'foreach',
|
|
297
|
+
items: '${invoices}',
|
|
298
|
+
do: { service: 'invoice', operation: 'process' }
|
|
299
|
+
}, message);
|
|
300
|
+
```
|
|
301
|
+
**Example** *(Fork-Join Parallel)*
|
|
302
|
+
```js
|
|
303
|
+
await orchestrator.handleControlFlow({
|
|
304
|
+
type: 'fork_join',
|
|
305
|
+
branches: [
|
|
306
|
+
{ service: 'inventory', operation: 'check' },
|
|
307
|
+
{ service: 'pricing', operation: 'calculate' }
|
|
308
|
+
],
|
|
309
|
+
joinStrategy: 'merge'
|
|
310
|
+
}, message);
|
|
311
|
+
```
|
|
312
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleIfStep"></a>
|
|
313
|
+
|
|
314
|
+
### @onlineapps/conn-orch-orchestrator~handleIfStep(step, message) ⇒ <code>Promise.<\*></code>
|
|
315
|
+
Handle if/else control flow
|
|
316
|
+
|
|
317
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
318
|
+
**Returns**: <code>Promise.<\*></code> - Branch execution result or null
|
|
319
|
+
|
|
320
|
+
| Param | Type | Description |
|
|
321
|
+
| --- | --- | --- |
|
|
322
|
+
| step | <code>IfStep</code> | If step definition |
|
|
323
|
+
| step.condition | <code>string</code> | Condition expression |
|
|
324
|
+
| [step.then] | <code>Object</code> | Branch for true condition |
|
|
325
|
+
| [step.else] | <code>Object</code> | Branch for false condition |
|
|
326
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
327
|
+
|
|
328
|
+
**Example**
|
|
329
|
+
```js
|
|
330
|
+
await orchestrator.handleIfStep({
|
|
331
|
+
condition: '${status} === "pending"',
|
|
332
|
+
then: { service: 'approval', operation: 'request' },
|
|
333
|
+
else: { service: 'notification', operation: 'send' }
|
|
334
|
+
}, message);
|
|
335
|
+
```
|
|
336
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleForeachStep"></a>
|
|
337
|
+
|
|
338
|
+
### @onlineapps/conn-orch-orchestrator~handleForeachStep(step, message) ⇒ <code>Promise.<Array></code>
|
|
339
|
+
Handle foreach iteration
|
|
340
|
+
|
|
341
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
342
|
+
**Returns**: <code>Promise.<Array></code> - Array of results from each iteration
|
|
343
|
+
**Throws**:
|
|
344
|
+
|
|
345
|
+
- <code>Error</code> If items is not an array
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
| Param | Type | Description |
|
|
349
|
+
| --- | --- | --- |
|
|
350
|
+
| step | <code>ForeachStep</code> | Foreach step definition |
|
|
351
|
+
| step.items | <code>string</code> \| <code>Array</code> | Items to iterate (or path to items) |
|
|
352
|
+
| step.do | <code>Object</code> | Step to execute for each item |
|
|
353
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
354
|
+
|
|
355
|
+
**Example**
|
|
356
|
+
```js
|
|
357
|
+
const results = await orchestrator.handleForeachStep({
|
|
358
|
+
items: '${invoice.line_items}',
|
|
359
|
+
do: { service: 'tax', operation: 'calculate' }
|
|
360
|
+
}, message);
|
|
361
|
+
```
|
|
362
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleForkJoinStep"></a>
|
|
363
|
+
|
|
364
|
+
### @onlineapps/conn-orch-orchestrator~handleForkJoinStep(step, message) ⇒ <code>Promise.<\*></code>
|
|
365
|
+
Handle fork-join parallel execution
|
|
366
|
+
|
|
367
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
368
|
+
**Returns**: <code>Promise.<\*></code> - Joined results based on strategy
|
|
369
|
+
**Throws**:
|
|
370
|
+
|
|
371
|
+
- <code>Error</code> If MQ client doesn't support fork-join
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
| Param | Type | Default | Description |
|
|
375
|
+
| --- | --- | --- | --- |
|
|
376
|
+
| step | <code>ForkJoinStep</code> | | Fork-join step definition |
|
|
377
|
+
| step.branches | <code>Array.<Object></code> | | Parallel branches to execute |
|
|
378
|
+
| [step.joinStrategy] | <code>string</code> | <code>"'merge'"</code> | Join strategy: 'merge', 'array', 'first' |
|
|
379
|
+
| [step.timeout] | <code>number</code> | | Overall timeout for all branches |
|
|
380
|
+
| message | <code>WorkflowMessage</code> | | Workflow message |
|
|
381
|
+
|
|
382
|
+
**Example**
|
|
383
|
+
```js
|
|
384
|
+
const result = await orchestrator.handleForkJoinStep({
|
|
385
|
+
branches: [
|
|
386
|
+
{ service: 'inventory', operation: 'reserve' },
|
|
387
|
+
{ service: 'payment', operation: 'authorize' },
|
|
388
|
+
{ service: 'shipping', operation: 'estimate' }
|
|
389
|
+
],
|
|
390
|
+
joinStrategy: 'merge',
|
|
391
|
+
timeout: 10000
|
|
392
|
+
}, message);
|
|
393
|
+
```
|
|
394
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleSwitchStep"></a>
|
|
395
|
+
|
|
396
|
+
### @onlineapps/conn-orch-orchestrator~handleSwitchStep(step, message) ⇒ <code>Promise.<\*></code>
|
|
397
|
+
Handle switch statement
|
|
398
|
+
|
|
399
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
400
|
+
**Returns**: <code>Promise.<\*></code> - Matched case execution result or null
|
|
401
|
+
|
|
402
|
+
| Param | Type | Description |
|
|
403
|
+
| --- | --- | --- |
|
|
404
|
+
| step | <code>SwitchStep</code> | Switch step definition |
|
|
405
|
+
| step.value | <code>string</code> | Value expression to switch on |
|
|
406
|
+
| step.cases | <code>Array.<Object></code> | Case definitions |
|
|
407
|
+
| [step.default] | <code>Object</code> | Default case |
|
|
408
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
409
|
+
|
|
410
|
+
**Example**
|
|
411
|
+
```js
|
|
412
|
+
await orchestrator.handleSwitchStep({
|
|
413
|
+
value: '${order.type}',
|
|
414
|
+
cases: [
|
|
415
|
+
{ value: 'standard', do: { service: 'shipping', operation: 'standard' } },
|
|
416
|
+
{ value: 'express', do: { service: 'shipping', operation: 'express' } }
|
|
417
|
+
],
|
|
418
|
+
default: { do: { service: 'shipping', operation: 'economy' } }
|
|
419
|
+
}, message);
|
|
420
|
+
```
|
|
421
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..routeToNextService"></a>
|
|
422
|
+
|
|
423
|
+
### @onlineapps/conn-orch-orchestrator~routeToNextService(message, nextService, stepResult, nextIndex) ⇒ <code>Promise.<void></code>
|
|
424
|
+
Route to next service in workflow
|
|
425
|
+
|
|
426
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
427
|
+
**Emits**: <code>MQClient#event:publish - Publishes to next service queue</code>
|
|
428
|
+
|
|
429
|
+
| Param | Type | Description |
|
|
430
|
+
| --- | --- | --- |
|
|
431
|
+
| message | <code>WorkflowMessage</code> | Current workflow message |
|
|
432
|
+
| nextService | <code>string</code> | Next service name |
|
|
433
|
+
| stepResult | <code>\*</code> | Current step result |
|
|
434
|
+
| nextIndex | <code>number</code> | Next step index |
|
|
435
|
+
|
|
436
|
+
**Example**
|
|
437
|
+
```js
|
|
438
|
+
await orchestrator.routeToNextService(
|
|
439
|
+
message,
|
|
440
|
+
'invoice-service',
|
|
441
|
+
{ processed: true, total: 1500 },
|
|
442
|
+
3
|
|
443
|
+
);
|
|
444
|
+
// Message published to 'invoice-service.workflow' queue
|
|
445
|
+
```
|
|
446
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..completeWorkflow"></a>
|
|
447
|
+
|
|
448
|
+
### @onlineapps/conn-orch-orchestrator~completeWorkflow(message, finalResult) ⇒ <code>Promise.<void></code>
|
|
449
|
+
Complete workflow
|
|
450
|
+
|
|
451
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
452
|
+
**Emits**: <code>MQClient#workflow.event:completed - Workflow completion event</code>
|
|
453
|
+
|
|
454
|
+
| Param | Type | Description |
|
|
455
|
+
| --- | --- | --- |
|
|
456
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
457
|
+
| finalResult | <code>\*</code> | Final workflow result |
|
|
458
|
+
|
|
459
|
+
**Example**
|
|
460
|
+
```js
|
|
461
|
+
await orchestrator.completeWorkflow(message, {
|
|
462
|
+
status: 'success',
|
|
463
|
+
invoice_id: 'inv-789',
|
|
464
|
+
total: 1500
|
|
465
|
+
});
|
|
466
|
+
```
|
|
467
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..handleWorkflowFailure"></a>
|
|
468
|
+
|
|
469
|
+
### @onlineapps/conn-orch-orchestrator~handleWorkflowFailure(message, error) ⇒ <code>Promise.<void></code>
|
|
470
|
+
Handle workflow failure
|
|
471
|
+
|
|
472
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
473
|
+
**Emits**: <code>MQClient#workflow.event:dlq - Sends to dead letter queue</code>
|
|
474
|
+
|
|
475
|
+
| Param | Type | Description |
|
|
476
|
+
| --- | --- | --- |
|
|
477
|
+
| message | <code>WorkflowMessage</code> | Workflow message |
|
|
478
|
+
| error | <code>Error</code> | Failure error |
|
|
479
|
+
|
|
480
|
+
**Example**
|
|
481
|
+
```js
|
|
482
|
+
await orchestrator.handleWorkflowFailure(message,
|
|
483
|
+
new Error('Service unavailable')
|
|
484
|
+
);
|
|
485
|
+
```
|
|
486
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..getStats"></a>
|
|
487
|
+
|
|
488
|
+
### @onlineapps/conn-orch-orchestrator~getStats() ⇒ <code>OrchestratorStats</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code> \| <code>number</code>
|
|
489
|
+
Get orchestrator statistics
|
|
490
|
+
|
|
491
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
492
|
+
**Returns**: <code>OrchestratorStats</code> - Current statistics<code>number</code> - stats.started - Workflows started<code>number</code> - stats.completed - Workflows completed<code>number</code> - stats.failed - Workflows failed<code>number</code> - stats.steps - Total steps processed<code>number</code> - stats.avgDuration - Average duration in ms<code>number</code> - stats.activeWorkflows - Currently active workflows
|
|
493
|
+
**Example**
|
|
494
|
+
```js
|
|
495
|
+
const stats = orchestrator.getStats();
|
|
496
|
+
console.log(`Success rate: ${stats.completed / stats.started * 100}%`);
|
|
497
|
+
console.log(`Average duration: ${stats.avgDuration}ms`);
|
|
498
|
+
```
|
|
499
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..resetStats"></a>
|
|
500
|
+
|
|
501
|
+
### @onlineapps/conn-orch-orchestrator~resetStats() ⇒ <code>void</code>
|
|
502
|
+
Reset statistics
|
|
503
|
+
|
|
504
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
505
|
+
**Example**
|
|
506
|
+
```js
|
|
507
|
+
orchestrator.resetStats();
|
|
508
|
+
// All counters reset to 0
|
|
509
|
+
```
|
|
510
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..create"></a>
|
|
511
|
+
|
|
512
|
+
### @onlineapps/conn-orch-orchestrator~create(config) ⇒ <code>OrchestratorConnector</code>
|
|
513
|
+
Factory function to create orchestrator instance
|
|
514
|
+
|
|
515
|
+
**Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
516
|
+
**Returns**: <code>OrchestratorConnector</code> - New orchestrator instance
|
|
517
|
+
|
|
518
|
+
| Param | Type | Description |
|
|
519
|
+
| --- | --- | --- |
|
|
520
|
+
| config | <code>Object</code> | Configuration object |
|
|
521
|
+
|
|
522
|
+
**Example**
|
|
523
|
+
```js
|
|
524
|
+
const orchestrator = OrchestratorConnector.create({
|
|
525
|
+
mqClient: mqConnector,
|
|
526
|
+
cookbook: cookbookConnector,
|
|
527
|
+
serviceName: 'invoice-service'
|
|
528
|
+
});
|
|
529
|
+
```
|
|
530
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..WorkflowMessage"></a>
|
|
531
|
+
|
|
532
|
+
### @onlineapps/conn-orch-orchestrator~WorkflowMessage : <code>Object</code>
|
|
533
|
+
**Kind**: inner typedef of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
534
|
+
**Properties**
|
|
535
|
+
|
|
536
|
+
| Name | Type | Default | Description |
|
|
537
|
+
| --- | --- | --- | --- |
|
|
538
|
+
| [workflow_id] | <code>string</code> | | Unique workflow identifier |
|
|
539
|
+
| cookbook | <code>Object</code> | | Cookbook definition |
|
|
540
|
+
| [current_step] | <code>number</code> | <code>0</code> | Current step index |
|
|
541
|
+
| [context] | <code>Object</code> | <code>{}</code> | Workflow context data |
|
|
542
|
+
| [trace] | <code>Array</code> | <code>[]</code> | Execution trace |
|
|
543
|
+
| [correlation_id] | <code>string</code> | | Correlation ID for tracing |
|
|
544
|
+
|
|
545
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..WorkflowResult"></a>
|
|
546
|
+
|
|
547
|
+
### @onlineapps/conn-orch-orchestrator~WorkflowResult : <code>Object</code>
|
|
548
|
+
**Kind**: inner typedef of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
549
|
+
**Properties**
|
|
550
|
+
|
|
551
|
+
| Name | Type | Description |
|
|
552
|
+
| --- | --- | --- |
|
|
553
|
+
| success | <code>boolean</code> | Whether workflow succeeded |
|
|
554
|
+
| workflowId | <code>string</code> | Workflow identifier |
|
|
555
|
+
| duration | <code>number</code> | Processing duration in ms |
|
|
556
|
+
|
|
557
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..ControlFlowStep"></a>
|
|
558
|
+
|
|
559
|
+
### @onlineapps/conn-orch-orchestrator~ControlFlowStep : <code>Object</code>
|
|
560
|
+
**Kind**: inner typedef of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
561
|
+
**Properties**
|
|
562
|
+
|
|
563
|
+
| Name | Type | Description |
|
|
564
|
+
| --- | --- | --- |
|
|
565
|
+
| type | <code>string</code> | Control flow type: 'if', 'foreach', 'fork_join', 'switch' |
|
|
566
|
+
| [condition] | <code>\*</code> | Condition for if steps |
|
|
567
|
+
| [items] | <code>\*</code> | Items for foreach steps |
|
|
568
|
+
| [branches] | <code>Array</code> | Branches for fork_join |
|
|
569
|
+
| [value] | <code>string</code> | Value for switch steps |
|
|
570
|
+
|
|
571
|
+
<a name="module_@onlineapps/conn-orch-orchestrator..OrchestratorStats"></a>
|
|
572
|
+
|
|
573
|
+
### @onlineapps/conn-orch-orchestrator~OrchestratorStats : <code>Object</code>
|
|
574
|
+
**Kind**: inner typedef of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
|
|
575
|
+
**Properties**
|
|
576
|
+
|
|
577
|
+
| Name | Type | Description |
|
|
578
|
+
| --- | --- | --- |
|
|
579
|
+
| started | <code>number</code> | Workflows started |
|
|
580
|
+
| completed | <code>number</code> | Workflows completed |
|
|
581
|
+
| failed | <code>number</code> | Workflows failed |
|
|
582
|
+
| steps | <code>number</code> | Total steps processed |
|
|
583
|
+
| avgDuration | <code>number</code> | Average duration in ms |
|
|
584
|
+
| activeWorkflows | <code>number</code> | Currently active workflows |
|
|
585
|
+
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
testEnvironment: 'node',
|
|
3
|
+
coverageDirectory: 'coverage',
|
|
4
|
+
collectCoverageFrom: [
|
|
5
|
+
'src/**/*.js',
|
|
6
|
+
'!src/**/*.test.js'
|
|
7
|
+
],
|
|
8
|
+
testMatch: [
|
|
9
|
+
'**/test/unit/**/*.test.js',
|
|
10
|
+
'**/test/component/**/*.test.js',
|
|
11
|
+
'**/test/integration/**/*.test.js'
|
|
12
|
+
],
|
|
13
|
+
testPathIgnorePatterns: [
|
|
14
|
+
'/node_modules/'
|
|
15
|
+
],
|
|
16
|
+
coverageThreshold: {
|
|
17
|
+
global: {
|
|
18
|
+
branches: 80,
|
|
19
|
+
functions: 80,
|
|
20
|
+
lines: 80,
|
|
21
|
+
statements: 80
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
moduleNameMapper: {
|
|
25
|
+
'^@/(.*)$': '<rootDir>/src/$1'
|
|
26
|
+
},
|
|
27
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
28
|
+
testTimeout: 10000
|
|
29
|
+
};
|
package/jest.setup.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Jest setup file for orchestrator tests
|
|
2
|
+
|
|
3
|
+
// Increase timeout for integration tests
|
|
4
|
+
if (process.env.TEST_TYPE === 'integration') {
|
|
5
|
+
jest.setTimeout(30000);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Mock console methods to reduce noise during tests
|
|
9
|
+
global.console = {
|
|
10
|
+
...console,
|
|
11
|
+
error: jest.fn(),
|
|
12
|
+
warn: jest.fn(),
|
|
13
|
+
// Keep info and debug for debugging
|
|
14
|
+
info: console.info,
|
|
15
|
+
debug: console.debug,
|
|
16
|
+
log: console.log
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Add custom matchers if needed
|
|
20
|
+
expect.extend({
|
|
21
|
+
toBeWorkflowMessage(received) {
|
|
22
|
+
const pass = received &&
|
|
23
|
+
typeof received === 'object' &&
|
|
24
|
+
'workflow_id' in received &&
|
|
25
|
+
'current_step' in received;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
pass,
|
|
29
|
+
message: () => pass
|
|
30
|
+
? `expected ${received} not to be a workflow message`
|
|
31
|
+
: `expected ${received} to be a workflow message with workflow_id and current_step`
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Setup test environment variables
|
|
37
|
+
process.env.NODE_ENV = 'test';
|
|
38
|
+
process.env.LOG_LEVEL = 'error';
|