@onlineapps/mq-client-core 1.0.6 → 1.0.8
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 +1 -1
- package/src/BaseClient.js +10 -0
- package/src/transports/rabbitmqClient.js +89 -15
package/package.json
CHANGED
package/src/BaseClient.js
CHANGED
|
@@ -146,7 +146,14 @@ class BaseClient {
|
|
|
146
146
|
if (typeof noAck === 'boolean') consumeOptions.noAck = noAck;
|
|
147
147
|
if (options.queueOptions) consumeOptions.queueOptions = options.queueOptions;
|
|
148
148
|
|
|
149
|
+
// CRITICAL: Log all consume() calls for transparency
|
|
150
|
+
console.log(`[BaseClient] [CONSUMER] Starting consume() for queue: ${queue} at ${new Date().toISOString()}`);
|
|
151
|
+
console.log(`[BaseClient] [CONSUMER] Options:`, JSON.stringify(consumeOptions, null, 2));
|
|
152
|
+
console.log(`[BaseClient] [CONSUMER] Transport type: ${this._transport?.constructor?.name || 'unknown'}`);
|
|
153
|
+
console.log(`[BaseClient] [CONSUMER] Connected: ${this._connected}`);
|
|
154
|
+
|
|
149
155
|
try {
|
|
156
|
+
const consumeStartTime = Date.now();
|
|
150
157
|
await this._transport.consume(
|
|
151
158
|
queue,
|
|
152
159
|
async (msg) => {
|
|
@@ -162,7 +169,10 @@ class BaseClient {
|
|
|
162
169
|
},
|
|
163
170
|
consumeOptions
|
|
164
171
|
);
|
|
172
|
+
const consumeEndTime = Date.now();
|
|
173
|
+
console.log(`[BaseClient] [CONSUMER] ✓ consume() completed for queue: ${queue} (took ${consumeEndTime - consumeStartTime}ms)`);
|
|
165
174
|
} catch (err) {
|
|
175
|
+
console.error(`[BaseClient] [CONSUMER] ✗ consume() failed for queue: ${queue}`, err.message);
|
|
166
176
|
throw new ConsumeError(`Failed to start consumer for queue "${queue}"`, queue, err);
|
|
167
177
|
}
|
|
168
178
|
}
|
|
@@ -203,29 +203,103 @@ class RabbitMQClient extends EventEmitter {
|
|
|
203
203
|
// Skip assertQueue for reply queues (they're already created with specific settings)
|
|
204
204
|
// Reply queues start with 'rpc.reply.' and are created as non-durable
|
|
205
205
|
if (!queue.startsWith('rpc.reply.')) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
206
|
+
// CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
|
|
207
|
+
// This prevents 406 PRECONDITION-FAILED errors from TTL mismatches
|
|
208
|
+
// Note: mq-client-core is for infrastructure services, but we need queueConfig from conn-infra-mq
|
|
209
|
+
// Try to load it - if it fails, we'll use defaults
|
|
210
|
+
let queueConfig = null;
|
|
211
|
+
try {
|
|
212
|
+
queueConfig = require('@onlineapps/conn-infra-mq/src/config/queueConfig');
|
|
213
|
+
} catch (requireErr) {
|
|
214
|
+
console.warn(`[RabbitMQClient] [mq-client-core] [CONSUMER] Cannot load queueConfig from @onlineapps/conn-infra-mq:`, requireErr.message);
|
|
215
|
+
console.warn(`[RabbitMQClient] [mq-client-core] [CONSUMER] Using default queue options (this may cause 406 errors if queue exists with different args)`);
|
|
216
|
+
}
|
|
217
|
+
const isInfraQueue = queueConfig.isInfrastructureQueue(queue);
|
|
218
|
+
const isBusinessQueue = queueConfig.isBusinessQueue(queue);
|
|
219
|
+
|
|
220
|
+
let queueOptions = options.queueOptions || { durable };
|
|
221
|
+
|
|
222
|
+
if (queueConfig) {
|
|
223
|
+
if (isInfraQueue) {
|
|
224
|
+
// Infrastructure queue - use central config
|
|
225
|
+
try {
|
|
226
|
+
const infraConfig = queueConfig.getInfrastructureQueueConfig(queue);
|
|
227
|
+
queueOptions = {
|
|
228
|
+
durable: infraConfig.durable !== false,
|
|
229
|
+
arguments: { ...infraConfig.arguments }
|
|
230
|
+
};
|
|
231
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Asserting infrastructure queue ${queue} with config from queueConfig`);
|
|
232
|
+
} catch (configErr) {
|
|
233
|
+
console.warn(`[RabbitMQClient] [mq-client-core] [CONSUMER] Infrastructure queue config not found for ${queue}, using default:`, configErr.message);
|
|
234
|
+
}
|
|
235
|
+
} else if (isBusinessQueue) {
|
|
236
|
+
// Business queue - use central config
|
|
237
|
+
try {
|
|
238
|
+
const parsed = queueConfig.parseBusinessQueue(queue);
|
|
239
|
+
if (parsed) {
|
|
240
|
+
const businessConfig = queueConfig.getBusinessQueueConfig(parsed.queueType, parsed.serviceName);
|
|
241
|
+
queueOptions = {
|
|
242
|
+
durable: businessConfig.durable !== false,
|
|
243
|
+
arguments: { ...businessConfig.arguments }
|
|
244
|
+
};
|
|
245
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Asserting business queue ${queue} with config from queueConfig`);
|
|
246
|
+
}
|
|
247
|
+
} catch (configErr) {
|
|
248
|
+
console.warn(`[RabbitMQClient] [mq-client-core] [CONSUMER] Business queue config not found for ${queue}, using default:`, configErr.message);
|
|
221
249
|
}
|
|
222
250
|
}
|
|
223
251
|
}
|
|
252
|
+
|
|
253
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Asserting queue ${queue} before consume() at ${new Date().toISOString()}`);
|
|
254
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Queue options:`, JSON.stringify(queueOptions, null, 2));
|
|
255
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] _queueChannel state: exists=${!!this._queueChannel}, closed=${this._queueChannel ? this._queueChannel.closed : 'N/A'}`);
|
|
256
|
+
|
|
257
|
+
// CRITICAL: Check if queue already exists with different arguments
|
|
258
|
+
// This can happen if sendToQueue() or amqplib's consume() auto-created it without TTL
|
|
259
|
+
try {
|
|
260
|
+
const queueInfo = await this._queueChannel.checkQueue(queue);
|
|
261
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Queue ${queue} already exists with arguments:`, JSON.stringify(queueInfo.messageCount !== undefined ? { messageCount: queueInfo.messageCount, consumerCount: queueInfo.consumerCount } : queueInfo));
|
|
262
|
+
// If queue exists, we need to check if arguments match
|
|
263
|
+
// Note: checkQueue() doesn't return arguments, so we'll try assertQueue() and catch 406
|
|
264
|
+
} catch (checkErr) {
|
|
265
|
+
if (checkErr.code === 404) {
|
|
266
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] Queue ${queue} does not exist (404), will be created with options`);
|
|
267
|
+
} else {
|
|
268
|
+
console.warn(`[RabbitMQClient] [mq-client-core] [CONSUMER] checkQueue() failed for ${queue}:`, checkErr.message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] About to call assertQueue(${queue}, ${JSON.stringify(queueOptions)})`);
|
|
274
|
+
await this._queueChannel.assertQueue(queue, queueOptions);
|
|
275
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] ✓ Queue ${queue} asserted successfully`);
|
|
276
|
+
} catch (assertErr) {
|
|
277
|
+
// If queue exists with different arguments (406), this is a CRITICAL ERROR
|
|
278
|
+
// We should NOT proceed - the root cause must be fixed
|
|
279
|
+
if (assertErr.code === 406) {
|
|
280
|
+
console.error(`[RabbitMQClient] [mq-client-core] [CONSUMER] ✗ CRITICAL: Queue ${queue} exists with different arguments!`);
|
|
281
|
+
console.error(`[RabbitMQClient] [mq-client-core] [CONSUMER] Error:`, assertErr.message);
|
|
282
|
+
console.error(`[RabbitMQClient] [mq-client-core] [CONSUMER] Expected options:`, JSON.stringify(queueOptions, null, 2));
|
|
283
|
+
console.error(`[RabbitMQClient] [mq-client-core] [CONSUMER] This means assertQueue() was called without parameters somewhere else. Root cause must be fixed!`);
|
|
284
|
+
throw new Error(`Cannot assertQueue ${queue}: queue exists with different arguments. Root cause: assertQueue() was called without parameters. Fix the root cause instead of proceeding.`);
|
|
285
|
+
} else {
|
|
286
|
+
// Other error - rethrow
|
|
287
|
+
throw assertErr;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
224
291
|
// Set prefetch if provided
|
|
225
292
|
if (typeof prefetch === 'number') {
|
|
226
293
|
this._channel.prefetch(prefetch);
|
|
227
294
|
}
|
|
228
295
|
|
|
296
|
+
// CRITICAL: Log before calling amqplib's consume()
|
|
297
|
+
// amqplib's consume() may internally call assertQueue() without parameters if queue doesn't exist
|
|
298
|
+
// This would create queue with default arguments (no TTL), causing 406 errors later
|
|
299
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] About to call amqplib's channel.consume(${queue})`);
|
|
300
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] ⚠ WARNING: amqplib's consume() may internally call assertQueue() WITHOUT parameters if queue doesn't exist`);
|
|
301
|
+
console.log(`[RabbitMQClient] [mq-client-core] [CONSUMER] ⚠ WARNING: We already asserted queue with correct parameters above - this should prevent auto-creation`);
|
|
302
|
+
|
|
229
303
|
await this._channel.consume(
|
|
230
304
|
queue,
|
|
231
305
|
async (msg) => {
|