@onlineapps/conn-orch-orchestrator 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/conn-orch-orchestrator",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Workflow orchestration connector for OA Drive - handles message routing and workflow execution",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -70,6 +70,14 @@ class WorkflowOrchestrator {
70
70
  // Validate cookbook structure
71
71
  this.cookbook.validateCookbook(cookbookDef);
72
72
 
73
+ // Ensure delivery configuration is preserved in context (required by Delivery Dispatcher)
74
+ // Delivery comes from cookbook.delivery (set by Gateway) and must be passed through to workflow.completed
75
+ const enrichedContext = {
76
+ ...context,
77
+ // Preserve delivery from cookbook if not already in context
78
+ delivery: context?.delivery || cookbookDef?.delivery || { handler: 'none' }
79
+ };
80
+
73
81
  // Find current step
74
82
  const step = cookbookDef.steps.find(s => s.id === current_step);
75
83
  if (!step) {
@@ -83,29 +91,52 @@ class WorkflowOrchestrator {
83
91
  return { skipped: true, reason: 'wrong_service' };
84
92
  }
85
93
 
94
+ // Publish workflow.progress to monitoring.workflow using unified helper
95
+ const { publishToMonitoringWorkflow } = require('@onlineapps/mq-client-core').monitoring;
96
+ try {
97
+ const stepIndex = cookbookDef.steps.findIndex(s => s.id === current_step);
98
+ await publishToMonitoringWorkflow(this.mqClient, {
99
+ event_type: 'progress',
100
+ workflow_id: workflow_id,
101
+ service_name: serviceName,
102
+ step_index: stepIndex >= 0 ? stepIndex : 0,
103
+ step_id: current_step,
104
+ cookbook: cookbookDef,
105
+ context: enrichedContext,
106
+ status: 'in_progress',
107
+ timestamp: new Date().toISOString()
108
+ }, this.logger, { workflow_id, step_id: current_step });
109
+ } catch (monitoringError) {
110
+ // Don't fail workflow if monitoring publish fails (helper already logs)
111
+ this.logger.warn('Failed to publish workflow.progress to monitoring', {
112
+ workflow_id,
113
+ error: monitoringError.message
114
+ });
115
+ }
116
+
86
117
  // Check cache if available
87
118
  let result;
88
119
  if (this.cache && step.type === 'task') {
89
- const cacheKey = this._getCacheKey(step, context);
120
+ const cacheKey = this._getCacheKey(step, enrichedContext);
90
121
  result = await this.cache.get(cacheKey);
91
122
 
92
123
  if (result) {
93
124
  this.logger.info('Cache hit', { step: step.id, cacheKey });
94
125
  } else {
95
126
  // Execute the step
96
- result = await this._executeStep(step, context, cookbookDef);
127
+ result = await this._executeStep(step, enrichedContext, cookbookDef);
97
128
  await this.cache.set(cacheKey, result, { ttl: 300 });
98
129
  }
99
130
  } else {
100
131
  // Execute without cache
101
- result = await this._executeStep(step, context, cookbookDef);
132
+ result = await this._executeStep(step, enrichedContext, cookbookDef);
102
133
  }
103
134
 
104
- // Update context with result
135
+ // Update context with result (preserve delivery from enrichedContext)
105
136
  const updatedContext = {
106
- ...context,
137
+ ...enrichedContext,
107
138
  steps: {
108
- ...context.steps,
139
+ ...enrichedContext.steps,
109
140
  [current_step]: result
110
141
  }
111
142
  };
@@ -118,8 +149,8 @@ class WorkflowOrchestrator {
118
149
  // Route to next step
119
150
  await this._routeToNextStep(nextStep, cookbookDef, updatedContext, workflow_id);
120
151
  } else {
121
- // Workflow completed
122
- await this._completeWorkflow(workflow_id, updatedContext);
152
+ // Workflow completed - pass serviceName for monitoring
153
+ await this._completeWorkflow(workflow_id, updatedContext, serviceName);
123
154
  }
124
155
 
125
156
  return {
@@ -294,12 +325,14 @@ class WorkflowOrchestrator {
294
325
  * @async
295
326
  * @param {string} workflow_id - Workflow ID
296
327
  * @param {Object} finalContext - Final workflow context
328
+ * @param {string} serviceName - Service name that completed the workflow
297
329
  */
298
- async _completeWorkflow(workflow_id, finalContext) {
330
+ async _completeWorkflow(workflow_id, finalContext, serviceName = 'unknown') {
299
331
  try {
300
332
  console.log(`[WorkflowOrchestrator] [PUBLISH] Preparing to publish workflow.completed for ${workflow_id}`);
301
333
  this.logger.info(`[WorkflowOrchestrator] [PUBLISH] Preparing to publish workflow.completed`, {
302
334
  workflow_id,
335
+ serviceName,
303
336
  hasMqClient: !!this.mqClient,
304
337
  mqClientConnected: this.mqClient?._connected
305
338
  });
@@ -312,6 +345,7 @@ class WorkflowOrchestrator {
312
345
  const workflowCompletedMessage = {
313
346
  workflow_id,
314
347
  status: 'completed',
348
+ service: serviceName, // Service that completed the workflow (for monitoring)
315
349
  delivery: delivery, // Delivery configuration from Gateway context (must be object)
316
350
  context: finalContext, // Full context for output resolution
317
351
  steps: finalContext?.steps || {}, // Steps results for output resolution
@@ -13,8 +13,9 @@ const CookbookConnector = require('@onlineapps/conn-orch-cookbook');
13
13
 
14
14
  // Skip integration tests if external services are not available
15
15
  const SKIP_INTEGRATION = process.env.SKIP_INTEGRATION === 'true';
16
- const RABBITMQ_URL = process.env.RABBITMQ_URL || 'amqp://localhost:5672';
17
- const REGISTRY_URL = process.env.REGISTRY_URL || 'http://localhost:4000';
16
+ const { requireEnv } = require('../../../../../tests/_helpers/test-config');
17
+ const RABBITMQ_URL = requireEnv('RABBITMQ_URL', 'RabbitMQ connection URL');
18
+ const REGISTRY_URL = requireEnv('REGISTRY_URL', 'Registry service URL');
18
19
 
19
20
  describe('Orchestrator - Integration Tests @integration', () => {
20
21
  if (SKIP_INTEGRATION) {