rabbitmq-sdk 0.0.1-security → 1.2.0
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.
Potentially problematic release.
This version of rabbitmq-sdk might be problematic. Click here for more details.
- package/.eslintrc.js +23 -0
- package/.kiro/specs/sdk-rabbitmq/design.md +369 -0
- package/.kiro/specs/sdk-rabbitmq/requirements.md +97 -0
- package/.kiro/specs/sdk-rabbitmq/tasks.md +248 -0
- package/README.md +273 -5
- package/bun.lock +790 -0
- package/config.example.json +13 -0
- package/dist/components/ConfigurationManager.d.ts +35 -0
- package/dist/components/ConfigurationManager.d.ts.map +1 -0
- package/dist/components/ConfigurationManager.js +118 -0
- package/dist/components/ConfigurationManager.js.map +1 -0
- package/dist/components/ConnectionManager.d.ts +93 -0
- package/dist/components/ConnectionManager.d.ts.map +1 -0
- package/dist/components/ConnectionManager.js +349 -0
- package/dist/components/ConnectionManager.js.map +1 -0
- package/dist/components/DLQHandler.d.ts +81 -0
- package/dist/components/DLQHandler.d.ts.map +1 -0
- package/dist/components/DLQHandler.js +228 -0
- package/dist/components/DLQHandler.js.map +1 -0
- package/dist/components/Logger.d.ts +77 -0
- package/dist/components/Logger.d.ts.map +1 -0
- package/dist/components/Logger.js +193 -0
- package/dist/components/Logger.js.map +1 -0
- package/dist/components/MessagePublisher.d.ts +49 -0
- package/dist/components/MessagePublisher.d.ts.map +1 -0
- package/dist/components/MessagePublisher.js +158 -0
- package/dist/components/MessagePublisher.js.map +1 -0
- package/dist/components/MessageSubscriber.d.ts +108 -0
- package/dist/components/MessageSubscriber.d.ts.map +1 -0
- package/dist/components/MessageSubscriber.js +503 -0
- package/dist/components/MessageSubscriber.js.map +1 -0
- package/dist/components/ResourceCreator.d.ts +89 -0
- package/dist/components/ResourceCreator.d.ts.map +1 -0
- package/dist/components/ResourceCreator.js +352 -0
- package/dist/components/ResourceCreator.js.map +1 -0
- package/dist/components/SdkRabbitmq.d.ts +103 -0
- package/dist/components/SdkRabbitmq.d.ts.map +1 -0
- package/dist/components/SdkRabbitmq.js +364 -0
- package/dist/components/SdkRabbitmq.js.map +1 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +20 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/IConfiguration.d.ts +35 -0
- package/dist/interfaces/IConfiguration.d.ts.map +1 -0
- package/dist/interfaces/IConfiguration.js +3 -0
- package/dist/interfaces/IConfiguration.js.map +1 -0
- package/dist/interfaces/IConnection.d.ts +21 -0
- package/dist/interfaces/IConnection.d.ts.map +1 -0
- package/dist/interfaces/IConnection.js +3 -0
- package/dist/interfaces/IConnection.js.map +1 -0
- package/dist/interfaces/IDLQ.d.ts +12 -0
- package/dist/interfaces/IDLQ.d.ts.map +1 -0
- package/dist/interfaces/IDLQ.js +3 -0
- package/dist/interfaces/IDLQ.js.map +1 -0
- package/dist/interfaces/IErrors.d.ts +33 -0
- package/dist/interfaces/IErrors.d.ts.map +1 -0
- package/dist/interfaces/IErrors.js +56 -0
- package/dist/interfaces/IErrors.js.map +1 -0
- package/dist/interfaces/ILogger.d.ts +14 -0
- package/dist/interfaces/ILogger.d.ts.map +1 -0
- package/dist/interfaces/ILogger.js +3 -0
- package/dist/interfaces/ILogger.js.map +1 -0
- package/dist/interfaces/IMessage.d.ts +52 -0
- package/dist/interfaces/IMessage.d.ts.map +1 -0
- package/dist/interfaces/IMessage.js +3 -0
- package/dist/interfaces/IMessage.js.map +1 -0
- package/dist/interfaces/IResource.d.ts +31 -0
- package/dist/interfaces/IResource.d.ts.map +1 -0
- package/dist/interfaces/IResource.js +3 -0
- package/dist/interfaces/IResource.js.map +1 -0
- package/dist/interfaces/ISdkRabbitmq.d.ts +17 -0
- package/dist/interfaces/ISdkRabbitmq.d.ts.map +1 -0
- package/dist/interfaces/ISdkRabbitmq.js +3 -0
- package/dist/interfaces/ISdkRabbitmq.js.map +1 -0
- package/dist/interfaces/index.d.ts +9 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +33 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/utils/configSchema.d.ts +8 -0
- package/dist/utils/configSchema.d.ts.map +1 -0
- package/dist/utils/configSchema.js +51 -0
- package/dist/utils/configSchema.js.map +1 -0
- package/docker-compose.yml +24 -0
- package/example.ts +65 -0
- package/examples/README-dynamic-routing.md +155 -0
- package/examples/bind-unbind-example.js +56 -0
- package/examples/test-chatbot-exchange.ts +83 -0
- package/examples/test-dynamic-routing-flow.js +299 -0
- package/examples/test-dynamic-routing-flow.ts +355 -0
- package/examples/test-no-disconnect.ts +0 -0
- package/examples/test-raw-rabbitmq.js +68 -0
- package/examples/test-same-channel.ts +81 -0
- package/examples/test-schedule-flow.ts +713 -0
- package/examples/test-simple-greeting.ts +66 -0
- package/examples/test-simple-schedule.ts +76 -0
- package/examples/test-wildcard.ts +364 -0
- package/jest.config.js +17 -0
- package/package.json +42 -4
- package/preinstall.js +1 -0
- package/prompts/test-dynamic-routing-flow.md +46 -0
- package/run.js +4 -0
- package/scripts/run-dynamic-routing-test.ts +31 -0
- package/src/.gitkeep +1 -0
- package/src/components/.gitkeep +1 -0
- package/src/components/ConfigurationManager.ts +104 -0
- package/src/components/ConnectionManager.ts +357 -0
- package/src/components/DLQHandler.ts +271 -0
- package/src/components/Logger.ts +224 -0
- package/src/components/MessagePublisher.ts +180 -0
- package/src/components/MessageSubscriber.ts +597 -0
- package/src/components/ResourceCreator.ts +411 -0
- package/src/components/SdkRabbitmq.ts +443 -0
- package/src/components/__tests__/ConfigurationManager.test.ts +357 -0
- package/src/components/__tests__/ConnectionManager.test.ts +387 -0
- package/src/components/__tests__/DLQHandler.test.ts +399 -0
- package/src/components/__tests__/Logger.test.ts +354 -0
- package/src/components/__tests__/MessagePublisher.test.ts +337 -0
- package/src/components/__tests__/MessageSubscriber.test.ts +542 -0
- package/src/components/__tests__/ResourceCreator.test.ts +465 -0
- package/src/components/__tests__/SdkRabbitmq.integration.test.ts +433 -0
- package/src/components/index.ts +8 -0
- package/src/index.ts +11 -0
- package/src/interfaces/.gitkeep +1 -0
- package/src/interfaces/IConfiguration.ts +38 -0
- package/src/interfaces/IConnection.ts +27 -0
- package/src/interfaces/IDLQ.ts +13 -0
- package/src/interfaces/IErrors.ts +53 -0
- package/src/interfaces/ILogger.ts +16 -0
- package/src/interfaces/IMessage.ts +65 -0
- package/src/interfaces/IResource.ts +35 -0
- package/src/interfaces/ISdkRabbitmq.ts +26 -0
- package/src/interfaces/index.ts +23 -0
- package/src/utils/.gitkeep +1 -0
- package/src/utils/configSchema.ts +58 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageSubscriber = void 0;
|
|
4
|
+
const IErrors_1 = require("../interfaces/IErrors");
|
|
5
|
+
const Logger_1 = require("./Logger");
|
|
6
|
+
/**
|
|
7
|
+
* MessageSubscriber handles message consumption from RabbitMQ queues
|
|
8
|
+
* Implements parameter validation, JSON deserialization, automatic resource creation, and DLQ handling
|
|
9
|
+
*/
|
|
10
|
+
class MessageSubscriber {
|
|
11
|
+
constructor(connectionManager, resourceCreator, dlqHandler, config) {
|
|
12
|
+
this.activeConsumers = new Map();
|
|
13
|
+
this.connectionManager = connectionManager;
|
|
14
|
+
this.resourceCreator = resourceCreator;
|
|
15
|
+
this.dlqHandler = dlqHandler;
|
|
16
|
+
this.logger = Logger_1.Logger.createComponentLogger('MessageSubscriber', config);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to messages from a queue
|
|
20
|
+
* @param exchange Exchange name (required)
|
|
21
|
+
* @param queue Queue name (required)
|
|
22
|
+
* @param routingKey Routing key for binding (required)
|
|
23
|
+
* @param callback Message callback function (required)
|
|
24
|
+
*/
|
|
25
|
+
async subscribe(exchange, queue, routingKey, callback) {
|
|
26
|
+
// Parameter validation - all parameters are required
|
|
27
|
+
this.validateSubscribeParameters(exchange, queue, routingKey, callback);
|
|
28
|
+
try {
|
|
29
|
+
// Automatic exchange and queue creation before subscribing
|
|
30
|
+
await this.ensureResourcesExist(exchange, queue, routingKey);
|
|
31
|
+
await this.connectionManager.executeOperation(async () => {
|
|
32
|
+
const connection = this.connectionManager.getConnection();
|
|
33
|
+
if (!connection) {
|
|
34
|
+
throw new IErrors_1.SubscriptionError('No active connection to RabbitMQ', {
|
|
35
|
+
exchange,
|
|
36
|
+
queue,
|
|
37
|
+
routingKey
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Create a dedicated channel for this consumer
|
|
41
|
+
const channel = await connection.createChannel();
|
|
42
|
+
try {
|
|
43
|
+
// Set prefetch to 1 for fair dispatch
|
|
44
|
+
await channel.prefetch(1);
|
|
45
|
+
// Start consuming messages
|
|
46
|
+
this.logger.info('🎯 SETTING UP CONSUMER', {
|
|
47
|
+
queue,
|
|
48
|
+
exchange,
|
|
49
|
+
routingKey
|
|
50
|
+
});
|
|
51
|
+
const consumerInfo = await channel.consume(queue, (message) => {
|
|
52
|
+
this.logger.info('📥 RAW MESSAGE RECEIVED', {
|
|
53
|
+
hasMessage: !!message,
|
|
54
|
+
queue,
|
|
55
|
+
exchange,
|
|
56
|
+
routingKey
|
|
57
|
+
});
|
|
58
|
+
if (message) {
|
|
59
|
+
this.logger.info('📋 MESSAGE DETAILS', {
|
|
60
|
+
exchange: message.fields.exchange,
|
|
61
|
+
routingKey: message.fields.routingKey,
|
|
62
|
+
deliveryTag: message.fields.deliveryTag,
|
|
63
|
+
contentLength: message.content.length
|
|
64
|
+
});
|
|
65
|
+
// Add queue name to message headers for DLQ handling
|
|
66
|
+
if (!message.properties.headers) {
|
|
67
|
+
message.properties.headers = {};
|
|
68
|
+
}
|
|
69
|
+
message.properties.headers['x-original-queue'] = queue;
|
|
70
|
+
this.handleMessage(message, callback, channel);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.logger.warn('⚠️ RECEIVED NULL MESSAGE', { queue });
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
noAck: false // We want manual acknowledgment
|
|
77
|
+
});
|
|
78
|
+
this.logger.info('✅ CONSUMER SETUP COMPLETE', {
|
|
79
|
+
consumerTag: consumerInfo.consumerTag,
|
|
80
|
+
queue
|
|
81
|
+
});
|
|
82
|
+
// Store consumer info for cleanup
|
|
83
|
+
this.activeConsumers.set(queue, {
|
|
84
|
+
channel,
|
|
85
|
+
consumerTag: consumerInfo.consumerTag
|
|
86
|
+
});
|
|
87
|
+
this.logger.logOperation('subscribe', `Successfully subscribed to queue`, {
|
|
88
|
+
queue,
|
|
89
|
+
exchange,
|
|
90
|
+
routingKey
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
// Close channel on error
|
|
95
|
+
this.logger.logError('❌ ERROR DURING CONSUMER SETUP - CLOSING CHANNEL', error, {
|
|
96
|
+
queue,
|
|
97
|
+
exchange,
|
|
98
|
+
routingKey
|
|
99
|
+
});
|
|
100
|
+
await channel.close();
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
// Detailed error logging with context
|
|
107
|
+
this.logSubscriptionError(error, exchange, queue, routingKey);
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Unsubscribe from a queue
|
|
113
|
+
* @param queue Queue name to unsubscribe from
|
|
114
|
+
*/
|
|
115
|
+
async unsubscribe(queue) {
|
|
116
|
+
if (!queue || typeof queue !== 'string') {
|
|
117
|
+
throw new IErrors_1.SubscriptionError('Queue parameter is required and must be a non-empty string', {
|
|
118
|
+
queue
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const consumerInfo = this.activeConsumers.get(queue);
|
|
122
|
+
if (!consumerInfo) {
|
|
123
|
+
this.logger.warn(`No active subscription found for queue`, { queue });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
// Cancel the consumer
|
|
128
|
+
await consumerInfo.channel.cancel(consumerInfo.consumerTag);
|
|
129
|
+
// Close the channel
|
|
130
|
+
await consumerInfo.channel.close();
|
|
131
|
+
// Remove from active consumers
|
|
132
|
+
this.activeConsumers.delete(queue);
|
|
133
|
+
this.logger.logOperation('unsubscribe', `Successfully unsubscribed from queue`, { queue });
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
137
|
+
this.logger.logError(`Error unsubscribing from queue`, error, { queue });
|
|
138
|
+
// Still remove from active consumers even if cleanup failed
|
|
139
|
+
this.activeConsumers.delete(queue);
|
|
140
|
+
throw new IErrors_1.SubscriptionError(`Failed to unsubscribe from queue '${queue}'`, {
|
|
141
|
+
queue,
|
|
142
|
+
error: errorMessage
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Handle incoming message
|
|
148
|
+
* @param message RabbitMQ message
|
|
149
|
+
* @param callback User callback function
|
|
150
|
+
* @param channel Channel for acknowledgment
|
|
151
|
+
*/
|
|
152
|
+
handleMessage(message, callback, channel) {
|
|
153
|
+
const queueName = this.getQueueNameFromMessage(message);
|
|
154
|
+
// Debug log to see if messages are arriving
|
|
155
|
+
this.logger.info('🔥 MESSAGE RECEIVED IN HANDLER', {
|
|
156
|
+
exchange: message.fields.exchange,
|
|
157
|
+
routingKey: message.fields.routingKey,
|
|
158
|
+
queue: queueName,
|
|
159
|
+
deliveryTag: message.fields.deliveryTag
|
|
160
|
+
});
|
|
161
|
+
try {
|
|
162
|
+
// JSON deserialization for incoming messages
|
|
163
|
+
const deserializedPayload = this.deserializeMessage(message);
|
|
164
|
+
// Create ack/nack functions for callback
|
|
165
|
+
const ack = () => {
|
|
166
|
+
try {
|
|
167
|
+
channel.ack(message);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
this.logger.logError('Error acknowledging message', error, {
|
|
171
|
+
deliveryTag: message.fields.deliveryTag,
|
|
172
|
+
queue: queueName
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const nack = async () => {
|
|
177
|
+
try {
|
|
178
|
+
await this.handleFailedMessage(message, queueName, channel);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
this.logger.logError('Error handling failed message', error, {
|
|
182
|
+
deliveryTag: message.fields.deliveryTag,
|
|
183
|
+
queue: queueName
|
|
184
|
+
});
|
|
185
|
+
// Fallback to regular nack with requeue
|
|
186
|
+
try {
|
|
187
|
+
channel.nack(message, false, true);
|
|
188
|
+
}
|
|
189
|
+
catch (nackError) {
|
|
190
|
+
this.logger.logError('Error negative acknowledging message', nackError, {
|
|
191
|
+
deliveryTag: message.fields.deliveryTag,
|
|
192
|
+
queue: queueName
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
// Debug log before invoking callback
|
|
198
|
+
this.logger.info('🚀 INVOKING USER CALLBACK', {
|
|
199
|
+
payloadType: typeof deserializedPayload,
|
|
200
|
+
queue: queueName
|
|
201
|
+
});
|
|
202
|
+
// Invoke callback with deserialized payload and ack/nack functions
|
|
203
|
+
callback(deserializedPayload, ack, nack);
|
|
204
|
+
this.logger.info('✅ USER CALLBACK COMPLETED', {
|
|
205
|
+
queue: queueName
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
this.logger.logError('Error handling message', error, {
|
|
210
|
+
exchange: message.fields.exchange,
|
|
211
|
+
routingKey: message.fields.routingKey,
|
|
212
|
+
deliveryTag: message.fields.deliveryTag,
|
|
213
|
+
queue: queueName
|
|
214
|
+
});
|
|
215
|
+
// Handle deserialization or other processing errors
|
|
216
|
+
this.handleFailedMessage(message, queueName, channel).catch(dlqError => {
|
|
217
|
+
this.logger.logError('Error routing failed message to DLQ', dlqError, {
|
|
218
|
+
deliveryTag: message.fields.deliveryTag,
|
|
219
|
+
queue: queueName
|
|
220
|
+
});
|
|
221
|
+
// Fallback to regular nack without requeue to avoid infinite loop
|
|
222
|
+
try {
|
|
223
|
+
channel.nack(message, false, false);
|
|
224
|
+
}
|
|
225
|
+
catch (nackError) {
|
|
226
|
+
this.logger.logError('Error negative acknowledging failed message', nackError, {
|
|
227
|
+
deliveryTag: message.fields.deliveryTag,
|
|
228
|
+
queue: queueName
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Validate subscribe method parameters
|
|
236
|
+
* @param exchange Exchange name
|
|
237
|
+
* @param queue Queue name
|
|
238
|
+
* @param routingKey Routing key
|
|
239
|
+
* @param callback Message callback function
|
|
240
|
+
*/
|
|
241
|
+
validateSubscribeParameters(exchange, queue, routingKey, callback) {
|
|
242
|
+
if (!exchange || typeof exchange !== 'string') {
|
|
243
|
+
throw new IErrors_1.SubscriptionError('Exchange parameter is required and must be a non-empty string', {
|
|
244
|
+
exchange,
|
|
245
|
+
queue,
|
|
246
|
+
routingKey
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (!queue || typeof queue !== 'string') {
|
|
250
|
+
throw new IErrors_1.SubscriptionError('Queue parameter is required and must be a non-empty string', {
|
|
251
|
+
exchange,
|
|
252
|
+
queue,
|
|
253
|
+
routingKey
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
if (!routingKey || typeof routingKey !== 'string') {
|
|
257
|
+
throw new IErrors_1.SubscriptionError('RoutingKey parameter is required and must be a non-empty string', {
|
|
258
|
+
exchange,
|
|
259
|
+
queue,
|
|
260
|
+
routingKey
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (!callback || typeof callback !== 'function') {
|
|
264
|
+
throw new IErrors_1.SubscriptionError('Callback parameter is required and must be a function', {
|
|
265
|
+
exchange,
|
|
266
|
+
queue,
|
|
267
|
+
routingKey,
|
|
268
|
+
callbackType: typeof callback
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Deserialize message content from JSON
|
|
274
|
+
* @param message RabbitMQ message
|
|
275
|
+
* @returns Deserialized payload
|
|
276
|
+
*/
|
|
277
|
+
deserializeMessage(message) {
|
|
278
|
+
try {
|
|
279
|
+
const contentString = message.content.toString('utf8');
|
|
280
|
+
return JSON.parse(contentString);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
throw new IErrors_1.SubscriptionError('Failed to deserialize message content from JSON', {
|
|
284
|
+
contentType: message.properties.contentType,
|
|
285
|
+
contentLength: message.content.length,
|
|
286
|
+
error: error instanceof Error ? error.message : 'Unknown deserialization error'
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Ensure exchange, queue, and binding exist before subscribing
|
|
292
|
+
* @param exchange Exchange name
|
|
293
|
+
* @param queue Queue name
|
|
294
|
+
* @param routingKey Routing key for binding
|
|
295
|
+
*/
|
|
296
|
+
async ensureResourcesExist(exchange, queue, routingKey) {
|
|
297
|
+
try {
|
|
298
|
+
// Create exchange if it doesn't exist
|
|
299
|
+
// Always use topic type by default
|
|
300
|
+
await this.resourceCreator.ensureExchange(exchange, 'topic');
|
|
301
|
+
// Create queue if it doesn't exist
|
|
302
|
+
await this.resourceCreator.ensureQueue(queue);
|
|
303
|
+
// Bind queue to exchange with routing key
|
|
304
|
+
await this.resourceCreator.bindQueue(queue, exchange, routingKey);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
throw new IErrors_1.SubscriptionError('Failed to ensure resources exist for subscription', {
|
|
308
|
+
exchange,
|
|
309
|
+
queue,
|
|
310
|
+
routingKey,
|
|
311
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Log subscription errors with detailed context
|
|
317
|
+
* @param error The error that occurred
|
|
318
|
+
* @param exchange Exchange name
|
|
319
|
+
* @param queue Queue name
|
|
320
|
+
* @param routingKey Routing key
|
|
321
|
+
*/
|
|
322
|
+
logSubscriptionError(error, exchange, queue, routingKey) {
|
|
323
|
+
this.logger.logError('Message subscription failed', error, {
|
|
324
|
+
exchange,
|
|
325
|
+
queue,
|
|
326
|
+
routingKey,
|
|
327
|
+
operation: 'subscribe'
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Get active consumer information for monitoring
|
|
332
|
+
*/
|
|
333
|
+
getActiveConsumers() {
|
|
334
|
+
return Array.from(this.activeConsumers.keys());
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Handle failed message by routing to DLQ or acknowledging based on configuration
|
|
338
|
+
* @param message Failed RabbitMQ message
|
|
339
|
+
* @param queueName Original queue name
|
|
340
|
+
* @param channel Channel for acknowledgment
|
|
341
|
+
*/
|
|
342
|
+
async handleFailedMessage(message, queueName, channel) {
|
|
343
|
+
try {
|
|
344
|
+
if (this.dlqHandler.isEnabled()) {
|
|
345
|
+
// Check retry count to determine if message should go to DLQ
|
|
346
|
+
const retryCount = this.getRetryCount(message);
|
|
347
|
+
const maxRetries = this.dlqHandler.getDLQConfig().maxRetries || 3;
|
|
348
|
+
if (retryCount >= maxRetries) {
|
|
349
|
+
// Route to DLQ after max retries exceeded
|
|
350
|
+
await this.dlqHandler.handleFailedMessage(message, queueName);
|
|
351
|
+
// Acknowledge the message since it's been routed to DLQ
|
|
352
|
+
channel.ack(message);
|
|
353
|
+
this.logger.info(`Message routed to DLQ after retries`, {
|
|
354
|
+
retryCount,
|
|
355
|
+
queue: queueName,
|
|
356
|
+
deliveryTag: message.fields.deliveryTag
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
// Increment retry count and requeue for retry
|
|
361
|
+
await this.requeueWithRetryCount(message, channel, retryCount + 1);
|
|
362
|
+
this.logger.info(`Message requeued for retry`, {
|
|
363
|
+
retryAttempt: retryCount + 1,
|
|
364
|
+
maxRetries,
|
|
365
|
+
queue: queueName,
|
|
366
|
+
deliveryTag: message.fields.deliveryTag
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
// DLQ is disabled, acknowledge failed messages without reprocessing
|
|
372
|
+
channel.ack(message);
|
|
373
|
+
this.logger.info(`DLQ disabled. Failed message acknowledged without reprocessing`, {
|
|
374
|
+
queue: queueName,
|
|
375
|
+
deliveryTag: message.fields.deliveryTag
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
this.logger.logError(`Failed to handle failed message`, error, {
|
|
381
|
+
queue: queueName,
|
|
382
|
+
deliveryTag: message.fields.deliveryTag
|
|
383
|
+
});
|
|
384
|
+
throw error;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get retry count from message headers
|
|
389
|
+
* @param message RabbitMQ message
|
|
390
|
+
* @returns Current retry count
|
|
391
|
+
*/
|
|
392
|
+
getRetryCount(message) {
|
|
393
|
+
if (!message.properties.headers) {
|
|
394
|
+
return 0;
|
|
395
|
+
}
|
|
396
|
+
return message.properties.headers['x-retry-count'] || 0;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Requeue message with incremented retry count
|
|
400
|
+
* @param message Original message
|
|
401
|
+
* @param channel Channel for operations
|
|
402
|
+
* @param retryCount New retry count
|
|
403
|
+
*/
|
|
404
|
+
async requeueWithRetryCount(message, channel, retryCount) {
|
|
405
|
+
try {
|
|
406
|
+
// Add retry delay if configured
|
|
407
|
+
const retryDelay = this.dlqHandler.getDLQConfig().retryDelay || 0;
|
|
408
|
+
if (retryDelay > 0) {
|
|
409
|
+
// Use setTimeout for delay before requeuing
|
|
410
|
+
setTimeout(() => {
|
|
411
|
+
this.republishWithRetryCount(message, channel, retryCount).catch(error => {
|
|
412
|
+
this.logger.logError('Error republishing message with retry count', error, {
|
|
413
|
+
retryCount,
|
|
414
|
+
deliveryTag: message.fields.deliveryTag
|
|
415
|
+
});
|
|
416
|
+
// Fallback to regular nack
|
|
417
|
+
try {
|
|
418
|
+
channel.nack(message, false, true);
|
|
419
|
+
}
|
|
420
|
+
catch (nackError) {
|
|
421
|
+
this.logger.logError('Error negative acknowledging message', nackError, {
|
|
422
|
+
deliveryTag: message.fields.deliveryTag
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
}, retryDelay);
|
|
427
|
+
// Acknowledge original message since we're republishing
|
|
428
|
+
channel.ack(message);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
// No delay, just nack with requeue
|
|
432
|
+
channel.nack(message, false, true);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
this.logger.logError('Error requeuing message with retry count', error, {
|
|
437
|
+
retryCount,
|
|
438
|
+
deliveryTag: message.fields.deliveryTag
|
|
439
|
+
});
|
|
440
|
+
// Fallback to regular nack
|
|
441
|
+
channel.nack(message, false, true);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Republish message with updated retry count
|
|
446
|
+
* @param message Original message
|
|
447
|
+
* @param channel Channel for operations
|
|
448
|
+
* @param retryCount New retry count
|
|
449
|
+
*/
|
|
450
|
+
async republishWithRetryCount(message, channel, retryCount) {
|
|
451
|
+
try {
|
|
452
|
+
// Update headers with retry count
|
|
453
|
+
const updatedHeaders = {
|
|
454
|
+
...message.properties.headers,
|
|
455
|
+
'x-retry-count': retryCount,
|
|
456
|
+
'x-retry-timestamp': Date.now()
|
|
457
|
+
};
|
|
458
|
+
const publishOptions = {
|
|
459
|
+
...message.properties,
|
|
460
|
+
headers: updatedHeaders
|
|
461
|
+
};
|
|
462
|
+
// Republish to the same exchange and routing key
|
|
463
|
+
const published = channel.publish(message.fields.exchange, message.fields.routingKey, message.content, publishOptions);
|
|
464
|
+
if (!published) {
|
|
465
|
+
throw new Error('Failed to republish message - channel buffer full');
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
const errorMessage = `Failed to republish message with retry count: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
|
470
|
+
throw new Error(errorMessage);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Extract queue name from message (fallback to routing key if not available)
|
|
475
|
+
* @param message RabbitMQ message
|
|
476
|
+
* @returns Queue name
|
|
477
|
+
*/
|
|
478
|
+
getQueueNameFromMessage(message) {
|
|
479
|
+
// Try to get queue name from headers first
|
|
480
|
+
if (message.properties.headers && message.properties.headers['x-original-queue']) {
|
|
481
|
+
return message.properties.headers['x-original-queue'];
|
|
482
|
+
}
|
|
483
|
+
// Fallback to routing key (common pattern)
|
|
484
|
+
return message.fields.routingKey || 'unknown-queue';
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Cleanup all active consumers (useful for shutdown)
|
|
488
|
+
*/
|
|
489
|
+
async cleanup() {
|
|
490
|
+
const queues = Array.from(this.activeConsumers.keys());
|
|
491
|
+
for (const queue of queues) {
|
|
492
|
+
try {
|
|
493
|
+
await this.unsubscribe(queue);
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
this.logger.logError(`Error cleaning up consumer for queue`, error, { queue });
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
this.logger.info('MessageSubscriber cleanup completed', { cleanedQueues: queues.length });
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
exports.MessageSubscriber = MessageSubscriber;
|
|
503
|
+
//# sourceMappingURL=MessageSubscriber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageSubscriber.js","sourceRoot":"","sources":["../../src/components/MessageSubscriber.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { IResourceCreator, QueueOptions, ExchangeOptions } from '../interfaces/IResource';
|
|
2
|
+
import { ConnectionManager } from './ConnectionManager';
|
|
3
|
+
import { IConfiguration } from '../interfaces/IConfiguration';
|
|
4
|
+
/**
|
|
5
|
+
* ResourceCreator handles automatic creation of exchanges, queues, and bindings
|
|
6
|
+
* Implements caching and existence checking to avoid duplicate creation attempts
|
|
7
|
+
*/
|
|
8
|
+
export declare class ResourceCreator implements IResourceCreator {
|
|
9
|
+
private connectionManager;
|
|
10
|
+
private createdExchanges;
|
|
11
|
+
private createdQueues;
|
|
12
|
+
private createdBindings;
|
|
13
|
+
private existingExchanges;
|
|
14
|
+
private existingQueues;
|
|
15
|
+
private logger;
|
|
16
|
+
constructor(connectionManager: ConnectionManager, config?: IConfiguration['logging']);
|
|
17
|
+
/**
|
|
18
|
+
* Check if exchange exists without creating it
|
|
19
|
+
* @param exchange Exchange name
|
|
20
|
+
* @returns Promise<boolean> indicating if exchange exists
|
|
21
|
+
*/
|
|
22
|
+
private checkExchangeExists;
|
|
23
|
+
/**
|
|
24
|
+
* Check if queue exists without creating it
|
|
25
|
+
* @param queue Queue name
|
|
26
|
+
* @returns Promise<boolean> indicating if queue exists
|
|
27
|
+
*/
|
|
28
|
+
private checkQueueExists;
|
|
29
|
+
/**
|
|
30
|
+
* Ensure exchange exists, create if it doesn't
|
|
31
|
+
* @param exchange Exchange name
|
|
32
|
+
* @param type Exchange type (default: 'direct')
|
|
33
|
+
* @param options Exchange options
|
|
34
|
+
*/
|
|
35
|
+
ensureExchange(exchange: string, type?: string, options?: ExchangeOptions): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Ensure queue exists, create if it doesn't
|
|
38
|
+
* @param queue Queue name
|
|
39
|
+
* @param options Queue options
|
|
40
|
+
*/
|
|
41
|
+
ensureQueue(queue: string, options?: QueueOptions): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Bind queue to exchange with routing key
|
|
44
|
+
* @param queue Queue name
|
|
45
|
+
* @param exchange Exchange name
|
|
46
|
+
* @param routingKey Routing key for binding
|
|
47
|
+
*/
|
|
48
|
+
bindQueue(queue: string, exchange: string, routingKey: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Unbind queue from exchange with routing key
|
|
51
|
+
* @param queue Queue name
|
|
52
|
+
* @param exchange Exchange name
|
|
53
|
+
* @param routingKey Routing key for unbinding
|
|
54
|
+
*/
|
|
55
|
+
unbindQueue(queue: string, exchange: string, routingKey: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Clear all caches (useful for testing or reset scenarios)
|
|
58
|
+
*/
|
|
59
|
+
clearCache(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Get cache statistics for monitoring
|
|
62
|
+
*/
|
|
63
|
+
getCacheStats(): {
|
|
64
|
+
created: {
|
|
65
|
+
exchanges: number;
|
|
66
|
+
queues: number;
|
|
67
|
+
bindings: number;
|
|
68
|
+
};
|
|
69
|
+
existing: {
|
|
70
|
+
exchanges: number;
|
|
71
|
+
queues: number;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Validate resource name format
|
|
76
|
+
* @param name Resource name to validate
|
|
77
|
+
* @param type Resource type for error messages
|
|
78
|
+
*/
|
|
79
|
+
private validateResourceName;
|
|
80
|
+
/**
|
|
81
|
+
* Enhanced ensure exchange with validation
|
|
82
|
+
*/
|
|
83
|
+
ensureExchangeWithValidation(exchange: string, type?: string, options?: ExchangeOptions): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Enhanced ensure queue with validation
|
|
86
|
+
*/
|
|
87
|
+
ensureQueueWithValidation(queue: string, options?: QueueOptions): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=ResourceCreator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceCreator.d.ts","sourceRoot":"","sources":["../../src/components/ResourceCreator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D;;;GAGG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,MAAM,CAAS;gBAEX,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC;IAKpF;;;;OAIG;YACW,mBAAmB;IA4BjC;;;;OAIG;YACW,gBAAgB;IA4B9B;;;;;OAKG;IACU,cAAc,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAgB,EACtB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC;IA8DhB;;;;OAIG;IACU,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4DlF;;;;;OAKG;IACU,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiD1F;;;;;OAKG;IACU,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4C5F;;OAEG;IACI,UAAU,IAAI,IAAI;IASzB;;OAEG;IACI,aAAa,IAAI;QACtB,OAAO,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;QACjE,QAAQ,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACjD;IAcD;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;IACU,4BAA4B,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAgB,EACtB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC;IAWhB;;OAEG;IACU,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAIjG"}
|