@onlineapps/infrastructure-tools 1.0.29 → 1.0.31

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/infrastructure-tools",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "description": "Infrastructure orchestration utilities for OA Drive infrastructure services (health tracking, queue initialization, service discovery)",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -22,7 +22,8 @@
22
22
  "dependencies": {
23
23
  "@onlineapps/mq-client-core": "^1.0.47",
24
24
  "@onlineapps/service-common": "^1.0.5",
25
- "uuid": "^9.0.1"
25
+ "uuid": "^9.0.1",
26
+ "@onlineapps/infra-logger": "^1.0.0"
26
27
  },
27
28
  "devDependencies": {
28
29
  "jest": "^29.7.0"
package/src/index.js CHANGED
@@ -38,6 +38,9 @@ const {
38
38
  const BaseClient = require('@onlineapps/mq-client-core');
39
39
  const queueConfig = require('@onlineapps/mq-client-core/src/config/queueConfig');
40
40
 
41
+ // Re-export infra-logger (infrastructure services should use infrastructure-tools, not infra-logger directly)
42
+ const { createLogger: createInfraLogger } = require('@onlineapps/infra-logger');
43
+
41
44
  const { initInfrastructureQueues } = require('./orchestration/initInfrastructureQueues');
42
45
  const {
43
46
  createHealthPublisher,
@@ -83,9 +86,12 @@ module.exports = {
83
86
  createBaseClientAdapter,
84
87
  createAmqplibAdapter,
85
88
 
86
- // Logger utility (consistent with conn-infra-mq pattern)
89
+ // Logger utilities
90
+ // createLogger - legacy logger wrapper (for backward compatibility)
87
91
  createLogger,
88
-
92
+ // createInfraLogger - structured logging from @onlineapps/infra-logger (preferred)
93
+ createInfraLogger,
94
+
89
95
  // Monitoring utilities
90
96
  sendQueueMismatchAlert
91
97
  };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { sendQueueMismatchAlert } = require('../monitoring/queueMismatchReporter');
4
+ const { createInfraLogger } = require('@onlineapps/infrastructure-tools');
4
5
 
5
6
  /**
6
7
  * initInfrastructureQueues.js
@@ -79,6 +80,17 @@ async function initInfrastructureQueues(channel, options = {}) {
79
80
  return workingChannel;
80
81
  };
81
82
 
83
+ // Structured log: queue initialization start
84
+ const log = createInfraLogger('infrastructure-tools', 'queue-init');
85
+ log.lifecycle(serviceName, 'INIT_START', {
86
+ handler: 'initInfrastructureQueues',
87
+ function: 'initInfrastructureQueues',
88
+ input: {
89
+ queues_count: queuesToCreate.length,
90
+ queues: queuesToCreate
91
+ }
92
+ });
93
+
82
94
  logger.log(`[QueueInit] Initializing ${queuesToCreate.length} infrastructure queues...`);
83
95
 
84
96
  for (const queueName of queuesToCreate) {
@@ -108,98 +120,11 @@ async function initInfrastructureQueues(channel, options = {}) {
108
120
  throw configError;
109
121
  }
110
122
 
111
- // CRITICAL: First check if queue exists and what parameters it has
112
- // This prevents 406 errors by proactively deleting queues with wrong parameters
113
- // Use a separate channel for checkQueue to avoid channel closure issues
114
- // NOTE: checkQueue() does NOT create queue - it only checks if it exists
115
- let queueExists = false;
116
- let queueNeedsRecreation = false;
117
- let checkChannelForDelete = null;
118
-
119
- try {
120
- // Use a separate channel for checking queue (to avoid closing workingChannel)
121
- // CRITICAL: checkQueue() does NOT create queue - it only checks existence
122
- checkChannelForDelete = await connection.createChannel();
123
- const queueInfo = await checkChannelForDelete.checkQueue(queueName);
124
- queueExists = true;
125
-
126
- // Check if queue has correct arguments
127
- const currentArgs = queueInfo.arguments || {};
128
- const expectedArgs = config.arguments || {};
129
-
130
- // Compare arguments (TTL, max-length, etc.)
131
- const argsMatch = Object.keys(expectedArgs).every(key => {
132
- return currentArgs[key] === expectedArgs[key];
133
- }) && Object.keys(currentArgs).every(key => {
134
- // Allow extra args in current queue, but required args must match
135
- return expectedArgs[key] === undefined || currentArgs[key] === expectedArgs[key];
136
- });
137
-
138
- if (!argsMatch) {
139
- logger.warn(`[QueueInit] ⚠ Queue ${queueName} exists with different arguments - will delete and recreate`, {
140
- current: currentArgs,
141
- expected: expectedArgs
142
- });
143
- queueNeedsRecreation = true;
144
- } else {
145
- logger.log(`[QueueInit] ✓ Queue ${queueName} exists with correct parameters`);
146
- // Close check channel if queue is OK
147
- try {
148
- await checkChannelForDelete.close();
149
- checkChannelForDelete = null;
150
- } catch (closeErr) {
151
- // Ignore
152
- }
153
- }
154
- } catch (checkError) {
155
- // Queue doesn't exist - will be created
156
- queueExists = false;
157
- logger.log(`[QueueInit] Queue ${queueName} does not exist (${checkError.code || checkError.message}) - will be created`);
158
- // Close check channel if queue doesn't exist
159
- if (checkChannelForDelete) {
160
- try {
161
- await checkChannelForDelete.close();
162
- checkChannelForDelete = null;
163
- } catch (closeErr) {
164
- // Ignore
165
- }
166
- }
167
- }
168
-
169
- // CRITICAL: If queue exists with wrong parameters, delete it first
170
- // This must be done BEFORE assertQueue to avoid 406 errors
171
- if (queueNeedsRecreation) {
172
- try {
173
- // Use the check channel for deletion (or create new one if check failed)
174
- const deleteChannel = checkChannelForDelete || await connection.createChannel();
175
- await deleteChannel.deleteQueue(queueName, { ifEmpty: false });
176
- logger.log(`[QueueInit] ✓ Deleted queue ${queueName} with incorrect parameters`);
177
- // Close delete channel after use
178
- try {
179
- await deleteChannel.close();
180
- } catch (closeErr) {
181
- // Ignore close errors
182
- }
183
- checkChannelForDelete = null;
184
-
185
- // Wait to ensure deletion is processed and no frames are pending
186
- await new Promise(resolve => setTimeout(resolve, 300));
187
- queueExists = false; // Queue no longer exists, will be created
188
- } catch (deleteError) {
189
- logger.error(`[QueueInit] ✗ Failed to delete queue ${queueName}:`, deleteError.message);
190
- // Clean up check channel if still open
191
- if (checkChannelForDelete) {
192
- try {
193
- await checkChannelForDelete.close();
194
- } catch (closeErr) {
195
- // Ignore
196
- }
197
- }
198
- throw new Error(`Cannot delete queue ${queueName} with incorrect parameters: ${deleteError.message}`);
199
- }
200
- }
201
-
202
- // CRITICAL: Now create/verify queue with correct parameters
123
+ // CRITICAL: Create/verify queue directly with assertQueue
124
+ // NOTE: We do NOT use checkQueue first because:
125
+ // - checkQueue throws 404 if queue doesn't exist, which closes the channel
126
+ // - assertQueue creates queue if it doesn't exist, OR verifies params if it does
127
+ // - If params mismatch, we get 406 PRECONDITION-FAILED which we handle below
203
128
  const ensureQueue = async () => {
204
129
  const activeChannel = await getChannel();
205
130
  return activeChannel.assertQueue(queueName, {
@@ -213,13 +138,15 @@ async function initInfrastructureQueues(channel, options = {}) {
213
138
  await ensureQueue();
214
139
  logger.log(`[QueueInit] ✓ Created/verified infrastructure queue: ${queueName}`);
215
140
  } catch (assertError) {
216
- logger.error(`[QueueInit] ✗ Failed to create/verify queue ${queueName}:`, {
141
+ logger.error(`[QueueInit] ✗ assertQueue failed for ${queueName}:`, {
217
142
  error: assertError.message,
218
143
  code: assertError.code,
219
144
  classId: assertError.classId,
220
145
  methodId: assertError.methodId
221
146
  });
147
+
222
148
  if (assertError.code === 406) {
149
+ // 406 PRECONDITION-FAILED: queue exists with different parameters
223
150
  if (alertOnMismatch) {
224
151
  try {
225
152
  await sendQueueMismatchAlert({
@@ -234,12 +161,11 @@ async function initInfrastructureQueues(channel, options = {}) {
234
161
  logger.warn('[QueueInit] Failed to send queue mismatch alert', alertError.message);
235
162
  }
236
163
  }
237
- logger.warn(
238
- `[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`
239
- );
164
+
165
+ logger.warn(`[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`);
166
+
240
167
  try {
241
- // CRITICAL: Use a fresh channel for delete operation to avoid closed channel errors
242
- // Close the current channel first to prevent it from receiving frames during deletion
168
+ // Close the current channel first (it's likely closed from 406 error anyway)
243
169
  if (workingChannel && !workingChannel.__queueInitClosed) {
244
170
  try {
245
171
  await workingChannel.close();
@@ -249,27 +175,23 @@ async function initInfrastructureQueues(channel, options = {}) {
249
175
  }
250
176
  }
251
177
 
178
+ // Delete queue with fresh channel
252
179
  const deleteChannel = await getChannel(true);
253
180
  await deleteChannel.deleteQueue(queueName, { ifEmpty: false });
254
181
  logger.log(`[QueueInit] ✓ Deleted queue ${queueName} with incorrect parameters`);
255
- // Close delete channel after use to avoid channel leaks
182
+
183
+ // Close delete channel
256
184
  try {
257
185
  await deleteChannel.close();
258
186
  } catch (closeErr) {
259
- // Ignore close errors - channel may already be closed
187
+ // Ignore close errors
260
188
  }
261
189
  } catch (deleteError) {
262
- logger.error(
263
- `[QueueInit] Failed to delete queue ${queueName}:`,
264
- deleteError.message
265
- );
266
- throw new Error(
267
- `Cannot delete queue ${queueName} with incorrect parameters: ${deleteError.message}`
268
- );
190
+ logger.error(`[QueueInit] ✗ Failed to delete queue ${queueName}:`, deleteError.message);
191
+ throw new Error(`Cannot delete queue ${queueName} with incorrect parameters: ${deleteError.message}`);
269
192
  }
270
193
 
271
- // CRITICAL: Recreate with correct parameters using a fresh channel
272
- // Wait a brief moment to ensure queue deletion is fully processed and no frames are pending
194
+ // Recreate with correct parameters using a fresh channel
273
195
  await new Promise(resolve => setTimeout(resolve, 200));
274
196
  const recreateChannel = await getChannel(true);
275
197
  try {
@@ -277,17 +199,14 @@ async function initInfrastructureQueues(channel, options = {}) {
277
199
  durable: config.durable !== false,
278
200
  arguments: { ...config.arguments }
279
201
  });
280
- logger.log(
281
- `[QueueInit] ✓ Recreated infrastructure queue: ${queueName} with correct parameters`
282
- );
283
- // Update workingChannel to the new channel for subsequent operations
202
+ logger.log(`[QueueInit] ✓ Recreated infrastructure queue: ${queueName} with correct parameters`);
284
203
  workingChannel = recreateChannel;
285
204
  } catch (recreateError) {
286
205
  logger.error(`[QueueInit] ✗ Failed to recreate ${queueName}:`, recreateError.message);
287
206
  throw recreateError;
288
207
  }
289
208
  } else {
290
- logger.error(`[QueueInit] Failed to create ${queueName}:`, assertError.message);
209
+ // Other error - rethrow
291
210
  throw assertError;
292
211
  }
293
212
  }
@@ -297,10 +216,17 @@ async function initInfrastructureQueues(channel, options = {}) {
297
216
  }
298
217
  }
299
218
 
219
+ // Structured log: queue initialization complete
220
+ log.lifecycle(serviceName, 'INIT_COMPLETE', {
221
+ handler: 'initInfrastructureQueues',
222
+ function: 'initInfrastructureQueues',
223
+ input: { queues_count: queuesToCreate.length },
224
+ output: { status: 'completed', queues_initialized: queuesToCreate.length }
225
+ });
226
+
300
227
  logger.log(`[QueueInit] Infrastructure queues initialization complete`);
301
228
  }
302
229
 
303
230
  module.exports = {
304
231
  initInfrastructureQueues
305
232
  };
306
-