@onlineapps/conn-orch-orchestrator 1.0.1 → 1.0.2

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 CHANGED
File without changes
package/README.md CHANGED
@@ -1,585 +1,138 @@
1
- <a name="module_@onlineapps/conn-orch-orchestrator"></a>
1
+ # @onlineapps/conn-orch-orchestrator
2
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.
3
+ Workflow orchestration coordinator managing complete workflow execution for OA Drive microservices.
7
4
 
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
5
+ ## Features
12
6
 
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.&lt;WorkflowResult&gt;</code> \| <code>boolean</code> \| <code>string</code> \| <code>number</code>
24
- * [~processStep(message)](#module_@onlineapps/conn-orch-orchestrator..processStep) ⇒ <code>Promise.&lt;\*&gt;</code>
25
- * [~handleControlFlow(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleControlFlow) ⇒ <code>Promise.&lt;\*&gt;</code>
26
- * [~handleIfStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleIfStep) ⇒ <code>Promise.&lt;\*&gt;</code>
27
- * [~handleForeachStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleForeachStep) ⇒ <code>Promise.&lt;Array&gt;</code>
28
- * [~handleForkJoinStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleForkJoinStep) ⇒ <code>Promise.&lt;\*&gt;</code>
29
- * [~handleSwitchStep(step, message)](#module_@onlineapps/conn-orch-orchestrator..handleSwitchStep) ⇒ <code>Promise.&lt;\*&gt;</code>
30
- * [~routeToNextService(message, nextService, stepResult, nextIndex)](#module_@onlineapps/conn-orch-orchestrator..routeToNextService) ⇒ <code>Promise.&lt;void&gt;</code>
31
- * [~completeWorkflow(message, finalResult)](#module_@onlineapps/conn-orch-orchestrator..completeWorkflow) ⇒ <code>Promise.&lt;void&gt;</code>
32
- * [~handleWorkflowFailure(message, error)](#module_@onlineapps/conn-orch-orchestrator..handleWorkflowFailure) ⇒ <code>Promise.&lt;void&gt;</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>
7
+ - 🎯 **Workflow coordination** - Complete workflow execution management
8
+ - 🔀 **Control flow handling** - If/else, switch, foreach, fork-join patterns
9
+ - 📊 **State management** - Workflow state tracking and persistence
10
+ - 🚦 **Step routing** - Intelligent routing to next services
11
+ - 📈 **Statistics tracking** - Workflow execution metrics
12
+ - **Async processing** - Non-blocking workflow execution
40
13
 
41
- <a name="module_@onlineapps/conn-orch-orchestrator.VERSION"></a>
14
+ ## Installation
42
15
 
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>&quot;&#x27;unknown&#x27;&quot;</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
- });
16
+ ```bash
17
+ npm install @onlineapps/conn-orch-orchestrator
153
18
  ```
154
- <a name="new_module_@onlineapps/conn-orch-orchestrator..OrchestratorConnector_new"></a>
155
19
 
156
- #### new OrchestratorConnector(config)
157
- Creates a new OrchestratorConnector instance
20
+ ## Quick Start
158
21
 
159
- **Throws**:
22
+ ```javascript
23
+ const { OrchestratorConnector } = require('@onlineapps/conn-orch-orchestrator');
160
24
 
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>&quot;&#x27;unknown&#x27;&quot;</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
25
  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
26
+ amqpUrl: process.env.AMQP_URL,
27
+ storageUrl: process.env.MINIO_URL
187
28
  });
188
- ```
189
- <a name="module_@onlineapps/conn-orch-orchestrator..processWorkflowMessage"></a>
190
29
 
191
- ### @onlineapps/conn-orch-orchestrator~processWorkflowMessage(message) <code>Promise.&lt;WorkflowResult&gt;</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.&lt;WorkflowResult&gt;</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
30
+ // Process workflow message
214
31
  const result = await orchestrator.processWorkflowMessage({
215
- workflow_id: 'wf-123',
216
- cookbook: cookbookDef,
217
- current_step: 0,
218
- context: { invoice_id: 'inv-456' }
32
+ workflowId: 'wf-123',
33
+ steps: [
34
+ { service: 'validation', operation: 'validate' },
35
+ { service: 'processing', operation: 'process' },
36
+ { service: 'notification', operation: 'notify' }
37
+ ],
38
+ currentStep: 0,
39
+ context: { /* workflow data */ }
219
40
  });
220
41
 
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.&lt;\*&gt;</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.&lt;\*&gt;</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
- });
42
+ // Get statistics
43
+ const stats = orchestrator.getStats();
44
+ console.log(`Processed: ${stats.processed}, Failed: ${stats.failed}`);
265
45
  ```
266
- <a name="module_@onlineapps/conn-orch-orchestrator..handleControlFlow"></a>
267
-
268
- ### @onlineapps/conn-orch-orchestrator~handleControlFlow(step, message) ⇒ <code>Promise.&lt;\*&gt;</code>
269
- Handle control flow steps (if, foreach, fork_join, switch)
270
46
 
271
- **Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
272
- **Returns**: <code>Promise.&lt;\*&gt;</code> - Control flow execution result
273
- **Throws**:
47
+ ## Configuration
274
48
 
275
- - <code>Error</code> If unknown control flow type
49
+ | Variable | Description | Default |
50
+ |----------|-------------|---------|
51
+ | `AMQP_URL` | RabbitMQ connection URL | required |
52
+ | `STORAGE_URL` | MinIO storage URL | required |
53
+ | `WORKFLOW_TIMEOUT` | Max workflow execution time (ms) | 300000 |
54
+ | `MAX_RETRIES` | Maximum retry attempts | 3 |
276
55
 
56
+ ## Control Flow Patterns
277
57
 
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({
58
+ ### If/Else
59
+ ```javascript
60
+ {
287
61
  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.&lt;\*&gt;</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.&lt;\*&gt;</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);
62
+ condition: { field: 'status', operator: 'equals', value: 'active' },
63
+ then: { service: 'activeHandler' },
64
+ else: { service: 'inactiveHandler' }
65
+ }
335
66
  ```
336
- <a name="module_@onlineapps/conn-orch-orchestrator..handleForeachStep"></a>
337
-
338
- ### @onlineapps/conn-orch-orchestrator~handleForeachStep(step, message) ⇒ <code>Promise.&lt;Array&gt;</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.&lt;Array&gt;</code> - Array of results from each iteration
343
- **Throws**:
344
-
345
- - <code>Error</code> If items is not an array
346
-
347
67
 
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);
68
+ ### Switch/Case
69
+ ```javascript
70
+ {
71
+ type: 'switch',
72
+ field: 'priority',
73
+ cases: {
74
+ 'high': { service: 'urgentHandler' },
75
+ 'normal': { service: 'standardHandler' },
76
+ 'low': { service: 'batchHandler' }
77
+ },
78
+ default: { service: 'defaultHandler' }
79
+ }
361
80
  ```
362
- <a name="module_@onlineapps/conn-orch-orchestrator..handleForkJoinStep"></a>
363
-
364
- ### @onlineapps/conn-orch-orchestrator~handleForkJoinStep(step, message) ⇒ <code>Promise.&lt;\*&gt;</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.&lt;\*&gt;</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.&lt;Object&gt;</code> | | Parallel branches to execute |
378
- | [step.joinStrategy] | <code>string</code> | <code>&quot;&#x27;merge&#x27;&quot;</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
81
 
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);
82
+ ### Foreach
83
+ ```javascript
84
+ {
85
+ type: 'foreach',
86
+ items: 'context.items',
87
+ step: { service: 'itemProcessor' }
88
+ }
393
89
  ```
394
- <a name="module_@onlineapps/conn-orch-orchestrator..handleSwitchStep"></a>
395
-
396
- ### @onlineapps/conn-orch-orchestrator~handleSwitchStep(step, message) ⇒ <code>Promise.&lt;\*&gt;</code>
397
- Handle switch statement
398
90
 
399
- **Kind**: inner method of [<code>@onlineapps/conn-orch-orchestrator</code>](#module_@onlineapps/conn-orch-orchestrator)
400
- **Returns**: <code>Promise.&lt;\*&gt;</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.&lt;Object&gt;</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' } }
91
+ ### Fork-Join
92
+ ```javascript
93
+ {
94
+ type: 'fork-join',
95
+ parallel: [
96
+ { service: 'validator' },
97
+ { service: 'enricher' },
98
+ { service: 'scorer' }
417
99
  ],
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.&lt;void&gt;</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
100
+ join: { service: 'aggregator' }
101
+ }
445
102
  ```
446
- <a name="module_@onlineapps/conn-orch-orchestrator..completeWorkflow"></a>
447
103
 
448
- ### @onlineapps/conn-orch-orchestrator~completeWorkflow(message, finalResult) ⇒ <code>Promise.&lt;void&gt;</code>
449
- Complete workflow
104
+ ## API Reference
450
105
 
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>
106
+ ### OrchestratorConnector
453
107
 
454
- | Param | Type | Description |
455
- | --- | --- | --- |
456
- | message | <code>WorkflowMessage</code> | Workflow message |
457
- | finalResult | <code>\*</code> | Final workflow result |
108
+ Main orchestrator class for workflow execution.
458
109
 
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>
110
+ #### Methods
468
111
 
469
- ### @onlineapps/conn-orch-orchestrator~handleWorkflowFailure(message, error) <code>Promise.&lt;void&gt;</code>
470
- Handle workflow failure
112
+ - `processWorkflowMessage(message)` - Process a workflow message
113
+ - `processStep(message)` - Process a single workflow step
114
+ - `handleControlFlow(step, message)` - Handle control flow steps
115
+ - `routeToNextService(message, nextService, result, nextIndex)` - Route to next service
116
+ - `completeWorkflow(message, result)` - Complete workflow execution
117
+ - `handleWorkflowFailure(message, error)` - Handle workflow failures
118
+ - `getStats()` - Get execution statistics
119
+ - `resetStats()` - Reset statistics
471
120
 
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>
121
+ ## Testing
474
122
 
475
- | Param | Type | Description |
476
- | --- | --- | --- |
477
- | message | <code>WorkflowMessage</code> | Workflow message |
478
- | error | <code>Error</code> | Failure error |
123
+ ```bash
124
+ # Run all tests
125
+ npm test
479
126
 
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>
127
+ # Run unit tests
128
+ npm run test:unit
487
129
 
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`);
130
+ # Run integration tests
131
+ npm run test:integration
498
132
  ```
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
133
 
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 |
134
+ ## 📚 Documentation
585
135
 
136
+ - [Complete Connectors Documentation](../../../docs/modules/connector.md)
137
+ - [Workflow Architecture](../../../docs/modules/workflow.md)
138
+ - [Testing Standards](../../../docs/modules/connector.md#testing-standards)
package/jest.config.js CHANGED
@@ -6,9 +6,9 @@ module.exports = {
6
6
  '!src/**/*.test.js'
7
7
  ],
8
8
  testMatch: [
9
- '**/test/unit/**/*.test.js',
10
- '**/test/component/**/*.test.js',
11
- '**/test/integration/**/*.test.js'
9
+ '**/tests/unit/**/*.test.js',
10
+ '**/tests/component/**/*.test.js',
11
+ '**/tests/integration/**/*.test.js'
12
12
  ],
13
13
  testPathIgnorePatterns: [
14
14
  '/node_modules/'
package/jest.setup.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/conn-orch-orchestrator",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Workflow orchestration connector for OA Drive - handles message routing and workflow execution",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -20,7 +20,7 @@
20
20
  "author": "OA Drive Team",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@onlineapps/conn-base-logger": "^1.0.0",
23
+ "@onlineapps/conn-base-monitoring": "^1.0.0",
24
24
  "@onlineapps/conn-infra-mq": "^1.1.0",
25
25
  "@onlineapps/conn-orch-registry": "^1.1.4",
26
26
  "@onlineapps/conn-orch-cookbook": "^2.0.0",
@@ -38,4 +38,4 @@
38
38
  "src/**/*.js"
39
39
  ]
40
40
  }
41
- }
41
+ }
@@ -130,11 +130,34 @@ class WorkflowOrchestrator {
130
130
  };
131
131
 
132
132
  } catch (error) {
133
- this.logger.error(`Workflow processing failed: ${error.message}`, {
134
- workflow_id,
135
- current_step,
136
- error: error.stack
137
- });
133
+ // Publish to workflow.failed queue
134
+ try {
135
+ console.log(`[WorkflowOrchestrator] [PUBLISH] Preparing to publish workflow.failed for ${workflow_id}`);
136
+ this.logger.error(`[WorkflowOrchestrator] [PUBLISH] Workflow processing failed: ${error.message}`, {
137
+ workflow_id,
138
+ current_step,
139
+ error: error.stack
140
+ });
141
+
142
+ await this.mqClient.publish('workflow.failed', {
143
+ workflow_id,
144
+ current_step,
145
+ error: error.message,
146
+ errorStack: error.stack,
147
+ failed_at: new Date().toISOString()
148
+ });
149
+
150
+ console.log(`[WorkflowOrchestrator] [PUBLISH] ✓ Successfully published workflow.failed for ${workflow_id}`);
151
+ this.logger.info(`[WorkflowOrchestrator] [PUBLISH] ✓ Published workflow.failed: ${workflow_id}`);
152
+ } catch (publishError) {
153
+ console.error(`[WorkflowOrchestrator] [PUBLISH] ✗ Failed to publish workflow.failed for ${workflow_id}:`, publishError.message);
154
+ this.logger.error(`[WorkflowOrchestrator] [PUBLISH] ✗ Failed to publish workflow.failed`, {
155
+ workflow_id,
156
+ originalError: error.message,
157
+ publishError: publishError.message
158
+ });
159
+ // Don't throw - original error is more important
160
+ }
138
161
 
139
162
  // Handle error
140
163
  if (this.errorHandler) {
@@ -273,13 +296,41 @@ class WorkflowOrchestrator {
273
296
  * @param {Object} finalContext - Final workflow context
274
297
  */
275
298
  async _completeWorkflow(workflow_id, finalContext) {
276
- await this.mqClient.publish('workflow.completed', {
277
- workflow_id,
278
- result: finalContext,
279
- completed_at: new Date().toISOString()
280
- });
299
+ try {
300
+ console.log(`[WorkflowOrchestrator] [PUBLISH] Preparing to publish workflow.completed for ${workflow_id}`);
301
+ this.logger.info(`[WorkflowOrchestrator] [PUBLISH] Preparing to publish workflow.completed`, {
302
+ workflow_id,
303
+ hasMqClient: !!this.mqClient,
304
+ mqClientConnected: this.mqClient?._connected
305
+ });
306
+
307
+ // Extract delivery configuration from context (passed from Gateway)
308
+ // Delivery Dispatcher requires: workflow_id, status, delivery (must be object, not null)
309
+ const delivery = finalContext?.delivery || { handler: 'none' }; // Default to 'none' handler if not provided
310
+
311
+ // Build message in format expected by Delivery Dispatcher
312
+ const workflowCompletedMessage = {
313
+ workflow_id,
314
+ status: 'completed',
315
+ delivery: delivery, // Delivery configuration from Gateway context (must be object)
316
+ context: finalContext, // Full context for output resolution
317
+ steps: finalContext?.steps || {}, // Steps results for output resolution
318
+ completed_at: new Date().toISOString()
319
+ };
320
+
321
+ await this.mqClient.publish('workflow.completed', workflowCompletedMessage);
281
322
 
282
- this.logger.info(`Workflow completed: ${workflow_id}`);
323
+ console.log(`[WorkflowOrchestrator] [PUBLISH] ✓ Successfully published workflow.completed for ${workflow_id}`);
324
+ this.logger.info(`[WorkflowOrchestrator] [PUBLISH] ✓ Workflow completed: ${workflow_id}`);
325
+ } catch (error) {
326
+ console.error(`[WorkflowOrchestrator] [PUBLISH] ✗ Failed to publish workflow.completed for ${workflow_id}:`, error.message);
327
+ this.logger.error(`[WorkflowOrchestrator] [PUBLISH] ✗ Failed to publish workflow.completed`, {
328
+ workflow_id,
329
+ error: error.message,
330
+ errorStack: error.stack
331
+ });
332
+ throw error; // Re-throw to allow ServiceWrapper to handle
333
+ }
283
334
  }
284
335
 
285
336
  /**
package/src/index.js CHANGED
File without changes
@@ -7,7 +7,7 @@
7
7
 
8
8
  const WorkflowOrchestrator = require('../../src/WorkflowOrchestrator');
9
9
 
10
- describe('Orchestrator - Component Tests', () => {
10
+ describe('Orchestrator - Component Tests @component', () => {
11
11
  let orchestrator;
12
12
  let mqClientStub;
13
13
  let registryClientStub;
@@ -16,7 +16,7 @@ const SKIP_INTEGRATION = process.env.SKIP_INTEGRATION === 'true';
16
16
  const RABBITMQ_URL = process.env.RABBITMQ_URL || 'amqp://localhost:5672';
17
17
  const REGISTRY_URL = process.env.REGISTRY_URL || 'http://localhost:4000';
18
18
 
19
- describe('Orchestrator - Integration Tests', () => {
19
+ describe('Orchestrator - Integration Tests @integration', () => {
20
20
  if (SKIP_INTEGRATION) {
21
21
  it.skip('Skipping integration tests (SKIP_INTEGRATION=true)', () => {});
22
22
  return;
@@ -7,7 +7,7 @@
7
7
 
8
8
  const WorkflowOrchestrator = require('../../src/WorkflowOrchestrator');
9
9
 
10
- describe('WorkflowOrchestrator - Unit Tests', () => {
10
+ describe('WorkflowOrchestrator - Unit Tests @unit', () => {
11
11
  let orchestrator;
12
12
  let mockMqClient;
13
13
  let mockRegistryClient;