@onlineapps/service-wrapper 2.0.45 → 2.0.47

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/service-wrapper",
3
- "version": "2.0.45",
3
+ "version": "2.0.47",
4
4
  "description": "Thin orchestration layer for microservices - delegates all infrastructure concerns to specialized connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1082,12 +1082,29 @@ class ServiceWrapper {
1082
1082
  result = await this._executeOperation(message.step.operation, message.input || {});
1083
1083
  } else if (this.orchestrator) {
1084
1084
  // Delegate to orchestrator for complex workflow processing
1085
+ // Validate required fields before processing
1086
+ if (!message.workflow_id && !message.workflowId) {
1087
+ throw new Error('Workflow message must have workflow_id or workflowId field');
1088
+ }
1089
+ if (!message.current_step && (!message.cookbook?.steps || message.cookbook.steps.length === 0)) {
1090
+ throw new Error('Workflow message must have current_step field or cookbook with at least one step');
1091
+ }
1092
+
1085
1093
  // Normalize message format: Gateway sends workflowId, orchestrator expects workflow_id
1086
1094
  const normalizedMessage = {
1087
1095
  ...message,
1088
1096
  workflow_id: message.workflow_id || message.workflowId,
1089
1097
  current_step: message.current_step || (message.cookbook?.steps?.[0]?.id)
1090
1098
  };
1099
+
1100
+ // Validate normalized message has required fields
1101
+ if (!normalizedMessage.workflow_id) {
1102
+ throw new Error('Failed to normalize workflow_id: message must have workflow_id or workflowId');
1103
+ }
1104
+ if (!normalizedMessage.current_step) {
1105
+ throw new Error('Failed to normalize current_step: message must have current_step or cookbook with steps');
1106
+ }
1107
+
1091
1108
  this.logger?.info(`[ServiceWrapper] Calling orchestrator.processWorkflowMessage`, {
1092
1109
  workflow_id: normalizedMessage.workflow_id,
1093
1110
  current_step: normalizedMessage.current_step,
@@ -1099,64 +1116,9 @@ class ServiceWrapper {
1099
1116
  throw new Error(`Unknown message format or operation: ${JSON.stringify(message)}`);
1100
1117
  }
1101
1118
 
1102
- // Send response to workflow.completed if workflow_id is present
1103
- if (message.workflow_id && this.mqClient) {
1104
- // Extract delivery configuration from context (passed from Gateway)
1105
- // Delivery can specify how to deliver the result (webhook, email, etc.)
1106
- const delivery = message.context?.delivery || null;
1107
-
1108
- const workflowResponse = {
1109
- workflow_id: message.workflow_id,
1110
- service: serviceName,
1111
- operation: message.step?.operation || message.operation,
1112
- status: 'completed',
1113
- output: result,
1114
- delivery: delivery, // Delivery configuration from Gateway context
1115
- flags,
1116
- timestamp: new Date().toISOString()
1117
- };
1118
-
1119
- try {
1120
- // Detailed logging before publish
1121
- this.logger?.info(`[ServiceWrapper] Preparing to publish workflow.completed`, {
1122
- workflowId: message.workflow_id,
1123
- service: serviceName,
1124
- operation: workflowResponse.operation,
1125
- mqClientConnected: this.mqClient._connected,
1126
- hasTransport: !!this.mqClient._transport,
1127
- hasChannel: !!(this.mqClient._transport?._channel)
1128
- });
1129
-
1130
- await this.mqClient.publish('workflow.completed', workflowResponse);
1131
-
1132
- // Log success with details
1133
- this.logger?.info(`✓ Workflow response sent to workflow.completed: ${message.workflow_id}`, {
1134
- workflowId: message.workflow_id,
1135
- queue: 'workflow.completed',
1136
- responseSize: JSON.stringify(workflowResponse).length
1137
- });
1138
- } catch (error) {
1139
- // Use error handler to log and handle the error
1140
- this.logger?.error(`[ServiceWrapper] Failed to publish workflow.completed`, {
1141
- workflowId: message.workflow_id,
1142
- queue: 'workflow.completed',
1143
- error: error.message,
1144
- errorStack: error.stack,
1145
- mqClientConnected: this.mqClient?._connected,
1146
- hasTransport: !!this.mqClient?._transport,
1147
- hasChannel: !!(this.mqClient?._transport?._channel)
1148
- });
1149
-
1150
- if (this.errorHandler) {
1151
- await this.errorHandler.logError({
1152
- moduleName: 'ServiceWrapper',
1153
- operation: 'sendWorkflowResponse',
1154
- error: error,
1155
- context: { workflowId: message.workflow_id, queue: 'workflow.completed' }
1156
- });
1157
- }
1158
- }
1159
- }
1119
+ // NOTE: workflow.completed is published by WorkflowOrchestrator._completeWorkflow()
1120
+ // ServiceWrapper should NOT publish here to avoid duplicate messages
1121
+ // If orchestrator is not used, ServiceWrapper would publish, but that's legacy path
1160
1122
 
1161
1123
  return result;
1162
1124