@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.
|
|
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
|
|
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:
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
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] ✗
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
164
|
+
|
|
165
|
+
logger.warn(`[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`);
|
|
166
|
+
|
|
240
167
|
try {
|
|
241
|
-
//
|
|
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
|
-
|
|
182
|
+
|
|
183
|
+
// Close delete channel
|
|
256
184
|
try {
|
|
257
185
|
await deleteChannel.close();
|
|
258
186
|
} catch (closeErr) {
|
|
259
|
-
// Ignore close errors
|
|
187
|
+
// Ignore close errors
|
|
260
188
|
}
|
|
261
189
|
} catch (deleteError) {
|
|
262
|
-
logger.error(
|
|
263
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|