@onlineapps/infrastructure-tools 1.0.29 → 1.0.30

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.30",
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": {
@@ -108,98 +108,11 @@ async function initInfrastructureQueues(channel, options = {}) {
108
108
  throw configError;
109
109
  }
110
110
 
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
111
+ // CRITICAL: Create/verify queue directly with assertQueue
112
+ // NOTE: We do NOT use checkQueue first because:
113
+ // - checkQueue throws 404 if queue doesn't exist, which closes the channel
114
+ // - assertQueue creates queue if it doesn't exist, OR verifies params if it does
115
+ // - If params mismatch, we get 406 PRECONDITION-FAILED which we handle below
203
116
  const ensureQueue = async () => {
204
117
  const activeChannel = await getChannel();
205
118
  return activeChannel.assertQueue(queueName, {
@@ -213,13 +126,15 @@ async function initInfrastructureQueues(channel, options = {}) {
213
126
  await ensureQueue();
214
127
  logger.log(`[QueueInit] ✓ Created/verified infrastructure queue: ${queueName}`);
215
128
  } catch (assertError) {
216
- logger.error(`[QueueInit] ✗ Failed to create/verify queue ${queueName}:`, {
129
+ logger.error(`[QueueInit] ✗ assertQueue failed for ${queueName}:`, {
217
130
  error: assertError.message,
218
131
  code: assertError.code,
219
132
  classId: assertError.classId,
220
133
  methodId: assertError.methodId
221
134
  });
135
+
222
136
  if (assertError.code === 406) {
137
+ // 406 PRECONDITION-FAILED: queue exists with different parameters
223
138
  if (alertOnMismatch) {
224
139
  try {
225
140
  await sendQueueMismatchAlert({
@@ -234,12 +149,11 @@ async function initInfrastructureQueues(channel, options = {}) {
234
149
  logger.warn('[QueueInit] Failed to send queue mismatch alert', alertError.message);
235
150
  }
236
151
  }
237
- logger.warn(
238
- `[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`
239
- );
152
+
153
+ logger.warn(`[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`);
154
+
240
155
  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
156
+ // Close the current channel first (it's likely closed from 406 error anyway)
243
157
  if (workingChannel && !workingChannel.__queueInitClosed) {
244
158
  try {
245
159
  await workingChannel.close();
@@ -249,27 +163,23 @@ async function initInfrastructureQueues(channel, options = {}) {
249
163
  }
250
164
  }
251
165
 
166
+ // Delete queue with fresh channel
252
167
  const deleteChannel = await getChannel(true);
253
168
  await deleteChannel.deleteQueue(queueName, { ifEmpty: false });
254
169
  logger.log(`[QueueInit] ✓ Deleted queue ${queueName} with incorrect parameters`);
255
- // Close delete channel after use to avoid channel leaks
170
+
171
+ // Close delete channel
256
172
  try {
257
173
  await deleteChannel.close();
258
174
  } catch (closeErr) {
259
- // Ignore close errors - channel may already be closed
175
+ // Ignore close errors
260
176
  }
261
177
  } 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
- );
178
+ logger.error(`[QueueInit] ✗ Failed to delete queue ${queueName}:`, deleteError.message);
179
+ throw new Error(`Cannot delete queue ${queueName} with incorrect parameters: ${deleteError.message}`);
269
180
  }
270
181
 
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
182
+ // Recreate with correct parameters using a fresh channel
273
183
  await new Promise(resolve => setTimeout(resolve, 200));
274
184
  const recreateChannel = await getChannel(true);
275
185
  try {
@@ -277,17 +187,14 @@ async function initInfrastructureQueues(channel, options = {}) {
277
187
  durable: config.durable !== false,
278
188
  arguments: { ...config.arguments }
279
189
  });
280
- logger.log(
281
- `[QueueInit] ✓ Recreated infrastructure queue: ${queueName} with correct parameters`
282
- );
283
- // Update workingChannel to the new channel for subsequent operations
190
+ logger.log(`[QueueInit] ✓ Recreated infrastructure queue: ${queueName} with correct parameters`);
284
191
  workingChannel = recreateChannel;
285
192
  } catch (recreateError) {
286
193
  logger.error(`[QueueInit] ✗ Failed to recreate ${queueName}:`, recreateError.message);
287
194
  throw recreateError;
288
195
  }
289
196
  } else {
290
- logger.error(`[QueueInit] Failed to create ${queueName}:`, assertError.message);
197
+ // Other error - rethrow
291
198
  throw assertError;
292
199
  }
293
200
  }
@@ -303,4 +210,3 @@ async function initInfrastructureQueues(channel, options = {}) {
303
210
  module.exports = {
304
211
  initInfrastructureQueues
305
212
  };
306
-