runmq 1.1.0 → 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.
- package/README.md +13 -12
- package/dist/index.cjs +282 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +282 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<img width="1479" height="612" alt="RunMQ-logo (4)" src="https://github.com/user-attachments/assets/50dc9187-26f9-4073-979b-31601c652e1f" />
|
|
3
|
-
<a href="https://
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<a href="https://www.npmjs.com/package/runmq">
|
|
4
|
+
<img src="https://badge.fury.io/js/runmq.svg?icon=si%3Anpm" alt="npm version" height="18">
|
|
5
|
+
</a>
|
|
6
6
|
<a href="https://github.com/semantic-release/semantic-release">
|
|
7
7
|
<img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg"/>
|
|
8
8
|
</a>
|
|
@@ -15,7 +15,6 @@ It combines RabbitMQ’s proven reliability with a modern developer experience
|
|
|
15
15
|
|
|
16
16
|
Whether you’re running <b>background jobs</b>, designing an <b>event-driven architecture</b>, or managing a <b>pub/sub event bus</b>, RunMQ provides everything you need — all in a <b>lightweight package</b> with a <b>simple DX</b>, <b>without the hassle of managing everything on your own</b>.
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
## Features
|
|
20
19
|
|
|
21
20
|
- **Reliable Message Processing with Retries**: Automatically retries failed messages with configurable delays and retry limits.
|
|
@@ -44,7 +43,7 @@ const runMQ = await RunMQ.start({
|
|
|
44
43
|
reconnectDelay: 5000, // Optional, default: 5000ms
|
|
45
44
|
maxReconnectAttempts: 5, // Optional, default: 5
|
|
46
45
|
management: {
|
|
47
|
-
url: "http://localhost:15673
|
|
46
|
+
url: "http://localhost:15673",
|
|
48
47
|
username: "guest",
|
|
49
48
|
password: "guest"
|
|
50
49
|
};
|
|
@@ -68,7 +67,8 @@ await runMQ.process('user.created', {
|
|
|
68
67
|
name: 'emailService', // Unique processor name (creates an isolated queue)
|
|
69
68
|
consumersCount: 2, // Process up to 2 messages concurrently
|
|
70
69
|
attempts: 3, // Retry failed messages up to 3 times
|
|
71
|
-
attemptsDelay: 2000
|
|
70
|
+
attemptsDelay: 2000, // Wait 2 seconds between retries
|
|
71
|
+
usePoliciesForDelay: true // highly recommended, default is false
|
|
72
72
|
}, async (message) => {
|
|
73
73
|
console.log('EmailService received:', message.message);
|
|
74
74
|
await sendEmail(message.message);
|
|
@@ -146,6 +146,7 @@ Publisher → Topic (email.send) → Queue: emailWorker → DLQ: emailWorker_dlq
|
|
|
146
146
|
- Dead Letter Queues allow failed messages to be captured without affecting other services.
|
|
147
147
|
- Schema validation ensures that only valid messages are processed; invalid messages can be routed to the DLQ automatically.
|
|
148
148
|
- Multiple concurrent workers can process jobs in parallel for high throughput.
|
|
149
|
+
- at anytime could be transformed into Event-Driven Architecture by adding more processors to the same topic.
|
|
149
150
|
|
|
150
151
|
<br>
|
|
151
152
|
|
|
@@ -200,11 +201,11 @@ await runMQ.process('order.placed', {
|
|
|
200
201
|
- Only messages matching the schema reach your business logic.
|
|
201
202
|
- DLQ ensures that invalid messages are captured and can be inspected later.
|
|
202
203
|
|
|
203
|
-
### Policies for
|
|
204
|
+
### Policies for attempts delay
|
|
204
205
|
|
|
205
206
|
RunMQ can leverage RabbitMQ policies to manage the delay between attempts, it's not used by default, however it's <b>highly recommended</b> to enable it.
|
|
206
207
|
|
|
207
|
-
- When `usePoliciesForDelay` is enabled, RunMQ creates delay queues with TTL configured via RabbitMQ policies rather than hard-coding TTL in the queue itself.
|
|
208
|
+
- When `usePoliciesForDelay` is enabled in consumer config, RunMQ creates delay queues with TTL configured via RabbitMQ policies rather than hard-coding TTL in the queue itself.
|
|
208
209
|
- Hard-coding the TTL requires manual queue re-declaration to change delays, which can involve deleting queues - making it cumbersome and error-prone.
|
|
209
210
|
- Policies allow dynamic updates to the TTL without recreating queues — you can change attempts delay anytime, and RunMQ will take care of the rest.
|
|
210
211
|
|
|
@@ -257,9 +258,9 @@ const runMQ = await RunMQ.start(config, new CustomLogger());
|
|
|
257
258
|
|
|
258
259
|
| Property | Type | Default | Description |
|
|
259
260
|
|----------|------|---------|-------------|
|
|
260
|
-
| `url` | `string` |
|
|
261
|
-
| `username` | `string` |
|
|
262
|
-
| `password` | `string` |
|
|
261
|
+
| `url` | `string` | - | The URL of the RabbitMQ management API. |
|
|
262
|
+
| `username` | `string` | - | Username for management API authentication. |
|
|
263
|
+
| `password` | `string` | - | Password for management API authentication. |
|
|
263
264
|
|
|
264
265
|
---
|
|
265
266
|
|
|
@@ -287,7 +288,7 @@ const runMQ = await RunMQ.start(config, new CustomLogger());
|
|
|
287
288
|
|
|
288
289
|
---
|
|
289
290
|
|
|
290
|
-
|
|
291
|
+
### 📦 Message Structure
|
|
291
292
|
|
|
292
293
|
| Property | Type | Description |
|
|
293
294
|
|----------|------|-------------|
|
package/dist/index.cjs
CHANGED
|
@@ -60,8 +60,8 @@ var RunMQException = class extends Error {
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
// src/core/clients/
|
|
64
|
-
var
|
|
63
|
+
// src/core/clients/RabbitMQClientAdapter.ts
|
|
64
|
+
var import_rabbitmq_client = require("rabbitmq-client");
|
|
65
65
|
|
|
66
66
|
// src/core/exceptions/Exceptions.ts
|
|
67
67
|
var Exceptions = class {
|
|
@@ -73,31 +73,228 @@ Exceptions.INVALID_MESSAGE_FORMAT = "MESSAGE_SHOULD_BE_VALID_RECORD";
|
|
|
73
73
|
Exceptions.UNSUPPORTED_SCHEMA = "UNSUPPORTED_SCHEMA";
|
|
74
74
|
Exceptions.FAILURE_TO_DEFINE_TTL_POLICY = "FAILURE_TO_DEFINE_TTL_POLICY";
|
|
75
75
|
|
|
76
|
-
// src/core/clients/
|
|
77
|
-
var
|
|
76
|
+
// src/core/clients/RabbitMQClientChannel.ts
|
|
77
|
+
var RabbitMQClientChannel = class {
|
|
78
|
+
constructor(channel) {
|
|
79
|
+
this.channel = channel;
|
|
80
|
+
}
|
|
81
|
+
async assertQueue(queue, options) {
|
|
82
|
+
const args = {};
|
|
83
|
+
if (options == null ? void 0 : options.deadLetterExchange) args["x-dead-letter-exchange"] = options.deadLetterExchange;
|
|
84
|
+
if (options == null ? void 0 : options.deadLetterRoutingKey) args["x-dead-letter-routing-key"] = options.deadLetterRoutingKey;
|
|
85
|
+
if (options == null ? void 0 : options.messageTtl) args["x-message-ttl"] = options.messageTtl;
|
|
86
|
+
if (options == null ? void 0 : options.arguments) Object.assign(args, options.arguments);
|
|
87
|
+
const result = await this.channel.queueDeclare({
|
|
88
|
+
queue,
|
|
89
|
+
durable: options == null ? void 0 : options.durable,
|
|
90
|
+
exclusive: options == null ? void 0 : options.exclusive,
|
|
91
|
+
autoDelete: options == null ? void 0 : options.autoDelete,
|
|
92
|
+
arguments: Object.keys(args).length > 0 ? args : void 0
|
|
93
|
+
});
|
|
94
|
+
return {
|
|
95
|
+
queue: result.queue,
|
|
96
|
+
messageCount: result.messageCount,
|
|
97
|
+
consumerCount: result.consumerCount
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async checkQueue(queue) {
|
|
101
|
+
const result = await this.channel.queueDeclare({
|
|
102
|
+
queue,
|
|
103
|
+
passive: true
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
queue: result.queue,
|
|
107
|
+
messageCount: result.messageCount,
|
|
108
|
+
consumerCount: result.consumerCount
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async deleteQueue(queue, options) {
|
|
112
|
+
const result = await this.channel.queueDelete({
|
|
113
|
+
queue,
|
|
114
|
+
ifUnused: options == null ? void 0 : options.ifUnused,
|
|
115
|
+
ifEmpty: options == null ? void 0 : options.ifEmpty
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
messageCount: result.messageCount
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async assertExchange(exchange, type, options) {
|
|
122
|
+
const args = {};
|
|
123
|
+
if (options == null ? void 0 : options.alternateExchange) args["alternate-exchange"] = options.alternateExchange;
|
|
124
|
+
if (options == null ? void 0 : options.arguments) Object.assign(args, options.arguments);
|
|
125
|
+
await this.channel.exchangeDeclare({
|
|
126
|
+
exchange,
|
|
127
|
+
type,
|
|
128
|
+
durable: options == null ? void 0 : options.durable,
|
|
129
|
+
internal: options == null ? void 0 : options.internal,
|
|
130
|
+
autoDelete: options == null ? void 0 : options.autoDelete,
|
|
131
|
+
arguments: Object.keys(args).length > 0 ? args : void 0
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
exchange
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async checkExchange(exchange) {
|
|
138
|
+
await this.channel.exchangeDeclare({
|
|
139
|
+
exchange,
|
|
140
|
+
passive: true
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
exchange
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async deleteExchange(exchange, options) {
|
|
147
|
+
await this.channel.exchangeDelete({
|
|
148
|
+
exchange,
|
|
149
|
+
ifUnused: options == null ? void 0 : options.ifUnused
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
async bindQueue(queue, source, pattern, args) {
|
|
153
|
+
await this.channel.queueBind({
|
|
154
|
+
queue,
|
|
155
|
+
exchange: source,
|
|
156
|
+
routingKey: pattern,
|
|
157
|
+
arguments: args
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
publish(exchange, routingKey, content, options) {
|
|
161
|
+
var _a2;
|
|
162
|
+
this.channel.basicPublish({
|
|
163
|
+
exchange,
|
|
164
|
+
routingKey,
|
|
165
|
+
correlationId: options == null ? void 0 : options.correlationId,
|
|
166
|
+
messageId: options == null ? void 0 : options.messageId,
|
|
167
|
+
headers: options == null ? void 0 : options.headers,
|
|
168
|
+
durable: options == null ? void 0 : options.persistent,
|
|
169
|
+
expiration: (_a2 = options == null ? void 0 : options.expiration) == null ? void 0 : _a2.toString(),
|
|
170
|
+
contentType: options == null ? void 0 : options.contentType,
|
|
171
|
+
contentEncoding: options == null ? void 0 : options.contentEncoding,
|
|
172
|
+
priority: options == null ? void 0 : options.priority,
|
|
173
|
+
replyTo: options == null ? void 0 : options.replyTo,
|
|
174
|
+
timestamp: options == null ? void 0 : options.timestamp,
|
|
175
|
+
type: options == null ? void 0 : options.type,
|
|
176
|
+
userId: options == null ? void 0 : options.userId,
|
|
177
|
+
appId: options == null ? void 0 : options.appId
|
|
178
|
+
}, content);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
async consume(queue, onMessage, options) {
|
|
182
|
+
const result = await this.channel.basicConsume({
|
|
183
|
+
queue,
|
|
184
|
+
consumerTag: options == null ? void 0 : options.consumerTag,
|
|
185
|
+
noLocal: options == null ? void 0 : options.noLocal,
|
|
186
|
+
noAck: options == null ? void 0 : options.noAck,
|
|
187
|
+
exclusive: options == null ? void 0 : options.exclusive,
|
|
188
|
+
arguments: options == null ? void 0 : options.arguments
|
|
189
|
+
}, (msg) => {
|
|
190
|
+
const body = msg.body;
|
|
191
|
+
const content = Buffer.isBuffer(body) ? body : typeof body === "string" ? Buffer.from(body) : Buffer.from(JSON.stringify(body));
|
|
192
|
+
const consumeMessage = {
|
|
193
|
+
content,
|
|
194
|
+
fields: {
|
|
195
|
+
consumerTag: msg.consumerTag,
|
|
196
|
+
deliveryTag: msg.deliveryTag,
|
|
197
|
+
redelivered: msg.redelivered,
|
|
198
|
+
exchange: msg.exchange,
|
|
199
|
+
routingKey: msg.routingKey
|
|
200
|
+
},
|
|
201
|
+
properties: {
|
|
202
|
+
contentType: msg.contentType,
|
|
203
|
+
contentEncoding: msg.contentEncoding,
|
|
204
|
+
headers: msg.headers || {},
|
|
205
|
+
deliveryMode: msg.durable ? 2 : 1,
|
|
206
|
+
priority: msg.priority,
|
|
207
|
+
correlationId: msg.correlationId,
|
|
208
|
+
replyTo: msg.replyTo,
|
|
209
|
+
expiration: msg.expiration,
|
|
210
|
+
messageId: msg.messageId,
|
|
211
|
+
timestamp: msg.timestamp,
|
|
212
|
+
type: msg.type,
|
|
213
|
+
userId: msg.userId,
|
|
214
|
+
appId: msg.appId
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
onMessage(consumeMessage);
|
|
218
|
+
});
|
|
219
|
+
return {
|
|
220
|
+
consumerTag: result.consumerTag
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
ack(message, allUpTo) {
|
|
224
|
+
this.channel.basicAck({
|
|
225
|
+
deliveryTag: message.fields.deliveryTag,
|
|
226
|
+
multiple: allUpTo
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
nack(message, allUpTo, requeue) {
|
|
230
|
+
this.channel.basicNack({
|
|
231
|
+
deliveryTag: message.fields.deliveryTag,
|
|
232
|
+
multiple: allUpTo,
|
|
233
|
+
requeue
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
async prefetch(count, global) {
|
|
237
|
+
await this.channel.basicQos({
|
|
238
|
+
prefetchCount: count,
|
|
239
|
+
global
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async close() {
|
|
243
|
+
await this.channel.close();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// src/core/clients/RabbitMQClientAdapter.ts
|
|
248
|
+
var RabbitMQClientAdapter = class {
|
|
78
249
|
constructor(config) {
|
|
79
250
|
this.config = config;
|
|
80
251
|
this.isConnected = false;
|
|
81
|
-
this.
|
|
252
|
+
this.acquiredChannels = [];
|
|
82
253
|
}
|
|
83
254
|
async connect() {
|
|
84
255
|
try {
|
|
85
|
-
if (this.
|
|
86
|
-
return this.
|
|
256
|
+
if (this.connection && this.isConnected) {
|
|
257
|
+
return this.connection;
|
|
87
258
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
this.channelModel.on("close", () => {
|
|
95
|
-
this.isConnected = false;
|
|
96
|
-
});
|
|
259
|
+
if (this.connection) {
|
|
260
|
+
try {
|
|
261
|
+
await this.connection.close();
|
|
262
|
+
} catch (e) {
|
|
263
|
+
}
|
|
264
|
+
this.connection = void 0;
|
|
97
265
|
}
|
|
98
|
-
|
|
266
|
+
this.connection = new import_rabbitmq_client.Connection({
|
|
267
|
+
url: this.config.url,
|
|
268
|
+
// Disable automatic retries - we handle retries at RunMQ level
|
|
269
|
+
retryLow: 100,
|
|
270
|
+
retryHigh: 200,
|
|
271
|
+
connectionTimeout: 5e3
|
|
272
|
+
});
|
|
273
|
+
this.connection.on("error", (err) => {
|
|
274
|
+
console.error("RabbitMQ connection error:", err);
|
|
275
|
+
this.isConnected = false;
|
|
276
|
+
});
|
|
277
|
+
this.connection.on("connection", () => {
|
|
278
|
+
this.isConnected = true;
|
|
279
|
+
});
|
|
280
|
+
this.connection.on("connection.blocked", (reason) => {
|
|
281
|
+
console.warn("RabbitMQ connection blocked:", reason);
|
|
282
|
+
});
|
|
283
|
+
this.connection.on("connection.unblocked", () => {
|
|
284
|
+
console.info("RabbitMQ connection unblocked");
|
|
285
|
+
});
|
|
286
|
+
await this.connection.onConnect(5e3, true);
|
|
287
|
+
this.isConnected = true;
|
|
288
|
+
return this.connection;
|
|
99
289
|
} catch (error) {
|
|
100
290
|
this.isConnected = false;
|
|
291
|
+
if (this.connection) {
|
|
292
|
+
try {
|
|
293
|
+
this.connection.close();
|
|
294
|
+
} catch (e) {
|
|
295
|
+
}
|
|
296
|
+
this.connection = void 0;
|
|
297
|
+
}
|
|
101
298
|
throw new RunMQException(
|
|
102
299
|
Exceptions.CONNECTION_NOT_ESTABLISHED,
|
|
103
300
|
{
|
|
@@ -107,25 +304,41 @@ var AmqplibClient = class {
|
|
|
107
304
|
}
|
|
108
305
|
}
|
|
109
306
|
async getChannel() {
|
|
110
|
-
|
|
307
|
+
const connection = await this.connect();
|
|
308
|
+
const rawChannel = await connection.acquire();
|
|
309
|
+
this.acquiredChannels.push(rawChannel);
|
|
310
|
+
return new RabbitMQClientChannel(rawChannel);
|
|
311
|
+
}
|
|
312
|
+
async getDefaultChannel() {
|
|
313
|
+
if (!this.defaultChannel) {
|
|
314
|
+
this.defaultChannel = await this.getChannel();
|
|
315
|
+
}
|
|
316
|
+
return this.defaultChannel;
|
|
111
317
|
}
|
|
112
318
|
async disconnect() {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
{
|
|
122
|
-
|
|
319
|
+
const conn = this.connection;
|
|
320
|
+
const channels = this.acquiredChannels;
|
|
321
|
+
this.connection = void 0;
|
|
322
|
+
this.defaultChannel = void 0;
|
|
323
|
+
this.isConnected = false;
|
|
324
|
+
this.acquiredChannels = [];
|
|
325
|
+
for (const channel of channels) {
|
|
326
|
+
try {
|
|
327
|
+
if (channel.active) {
|
|
328
|
+
await channel.close();
|
|
123
329
|
}
|
|
124
|
-
)
|
|
330
|
+
} catch (e) {
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (conn) {
|
|
334
|
+
try {
|
|
335
|
+
await conn.close();
|
|
336
|
+
} catch (e) {
|
|
337
|
+
}
|
|
125
338
|
}
|
|
126
339
|
}
|
|
127
340
|
isActive() {
|
|
128
|
-
return this.
|
|
341
|
+
return this.connection !== void 0 && this.isConnected;
|
|
129
342
|
}
|
|
130
343
|
};
|
|
131
344
|
|
|
@@ -175,6 +388,23 @@ var RabbitMQMessage = class _RabbitMQMessage {
|
|
|
175
388
|
this.amqpMessage = amqpMessage;
|
|
176
389
|
this.headers = headers;
|
|
177
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Acknowledges the message.
|
|
393
|
+
*/
|
|
394
|
+
ack() {
|
|
395
|
+
if (this.amqpMessage) {
|
|
396
|
+
this.channel.ack(this.amqpMessage);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Negatively acknowledges the message.
|
|
401
|
+
* @param requeue - Whether to requeue the message (default: false)
|
|
402
|
+
*/
|
|
403
|
+
nack(requeue = false) {
|
|
404
|
+
if (this.amqpMessage) {
|
|
405
|
+
this.channel.nack(this.amqpMessage, false, requeue);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
178
408
|
static from(messageData, channel, props, amqpMessage = null) {
|
|
179
409
|
return new _RabbitMQMessage(
|
|
180
410
|
messageData,
|
|
@@ -195,7 +425,7 @@ var RunMQSucceededMessageAcknowledgerProcessor = class {
|
|
|
195
425
|
async consume(message) {
|
|
196
426
|
const result = await this.consumer.consume(message);
|
|
197
427
|
if (result) {
|
|
198
|
-
message.
|
|
428
|
+
message.ack();
|
|
199
429
|
}
|
|
200
430
|
return result;
|
|
201
431
|
}
|
|
@@ -210,7 +440,7 @@ var RunMQFailedMessageRejecterProcessor = class {
|
|
|
210
440
|
try {
|
|
211
441
|
return await this.consumer.consume(message);
|
|
212
442
|
} catch (e) {
|
|
213
|
-
message.
|
|
443
|
+
message.nack(false);
|
|
214
444
|
return false;
|
|
215
445
|
}
|
|
216
446
|
}
|
|
@@ -271,7 +501,7 @@ var RunMQRetriesCheckerProcessor = class {
|
|
|
271
501
|
}
|
|
272
502
|
acknowledgeMessage(message) {
|
|
273
503
|
try {
|
|
274
|
-
message.
|
|
504
|
+
message.ack();
|
|
275
505
|
} catch (e) {
|
|
276
506
|
const error = new Error("A message acknowledge failed after publishing to final dead letter");
|
|
277
507
|
this.logger.error(error.message, { cause: e instanceof Error ? e.message : String(e) });
|
|
@@ -703,8 +933,7 @@ var RunMQTTLPolicyManager = class {
|
|
|
703
933
|
|
|
704
934
|
// src/core/consumer/RunMQConsumerCreator.ts
|
|
705
935
|
var RunMQConsumerCreator = class {
|
|
706
|
-
constructor(
|
|
707
|
-
this.defaultChannel = defaultChannel;
|
|
936
|
+
constructor(client, logger, managementConfig) {
|
|
708
937
|
this.client = client;
|
|
709
938
|
this.logger = logger;
|
|
710
939
|
this.ttlPolicyManager = new RunMQTTLPolicyManager(logger, managementConfig);
|
|
@@ -756,12 +985,13 @@ var RunMQConsumerCreator = class {
|
|
|
756
985
|
}
|
|
757
986
|
async assertQueues(consumerConfiguration) {
|
|
758
987
|
var _a2, _b;
|
|
759
|
-
await this.
|
|
988
|
+
const defaultChannel = await this.client.getDefaultChannel();
|
|
989
|
+
await defaultChannel.assertQueue(consumerConfiguration.processorConfig.name, {
|
|
760
990
|
durable: true,
|
|
761
991
|
deadLetterExchange: Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME,
|
|
762
992
|
deadLetterRoutingKey: consumerConfiguration.processorConfig.name
|
|
763
993
|
});
|
|
764
|
-
await
|
|
994
|
+
await defaultChannel.assertQueue(ConsumerCreatorUtils.getDLQTopicName(consumerConfiguration.processorConfig.name), {
|
|
765
995
|
durable: true,
|
|
766
996
|
deadLetterExchange: Constants.ROUTER_EXCHANGE_NAME,
|
|
767
997
|
deadLetterRoutingKey: consumerConfiguration.processorConfig.name
|
|
@@ -770,7 +1000,7 @@ var RunMQConsumerCreator = class {
|
|
|
770
1000
|
const messageDelay = (_a2 = consumerConfiguration.processorConfig.attemptsDelay) != null ? _a2 : DEFAULTS.PROCESSING_RETRY_DELAY;
|
|
771
1001
|
const policiesForTTL = (_b = consumerConfiguration.processorConfig.usePoliciesForDelay) != null ? _b : false;
|
|
772
1002
|
if (!policiesForTTL) {
|
|
773
|
-
await
|
|
1003
|
+
await defaultChannel.assertQueue(retryDelayQueueName, {
|
|
774
1004
|
durable: true,
|
|
775
1005
|
deadLetterExchange: Constants.ROUTER_EXCHANGE_NAME,
|
|
776
1006
|
messageTtl: messageDelay
|
|
@@ -782,7 +1012,7 @@ var RunMQConsumerCreator = class {
|
|
|
782
1012
|
messageDelay
|
|
783
1013
|
);
|
|
784
1014
|
if (result) {
|
|
785
|
-
await
|
|
1015
|
+
await defaultChannel.assertQueue(retryDelayQueueName, {
|
|
786
1016
|
durable: true,
|
|
787
1017
|
deadLetterExchange: Constants.ROUTER_EXCHANGE_NAME
|
|
788
1018
|
});
|
|
@@ -796,22 +1026,23 @@ var RunMQConsumerCreator = class {
|
|
|
796
1026
|
);
|
|
797
1027
|
}
|
|
798
1028
|
async bindQueues(consumerConfiguration) {
|
|
799
|
-
await this.
|
|
1029
|
+
const defaultChannel = await this.client.getDefaultChannel();
|
|
1030
|
+
await defaultChannel.bindQueue(
|
|
800
1031
|
consumerConfiguration.processorConfig.name,
|
|
801
1032
|
Constants.ROUTER_EXCHANGE_NAME,
|
|
802
1033
|
consumerConfiguration.topic
|
|
803
1034
|
);
|
|
804
|
-
await
|
|
1035
|
+
await defaultChannel.bindQueue(
|
|
805
1036
|
consumerConfiguration.processorConfig.name,
|
|
806
1037
|
Constants.ROUTER_EXCHANGE_NAME,
|
|
807
1038
|
consumerConfiguration.processorConfig.name
|
|
808
1039
|
);
|
|
809
|
-
await
|
|
1040
|
+
await defaultChannel.bindQueue(
|
|
810
1041
|
ConsumerCreatorUtils.getRetryDelayTopicName(consumerConfiguration.processorConfig.name),
|
|
811
1042
|
Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME,
|
|
812
1043
|
consumerConfiguration.processorConfig.name
|
|
813
1044
|
);
|
|
814
|
-
await
|
|
1045
|
+
await defaultChannel.bindQueue(
|
|
815
1046
|
ConsumerCreatorUtils.getDLQTopicName(consumerConfiguration.processorConfig.name),
|
|
816
1047
|
Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME,
|
|
817
1048
|
ConsumerCreatorUtils.getDLQTopicName(consumerConfiguration.processorConfig.name)
|
|
@@ -877,7 +1108,7 @@ var RunMQ = class _RunMQ {
|
|
|
877
1108
|
reconnectDelay: (_a2 = config.reconnectDelay) != null ? _a2 : DEFAULTS.RECONNECT_DELAY,
|
|
878
1109
|
maxReconnectAttempts: (_b = config.maxReconnectAttempts) != null ? _b : DEFAULTS.MAX_RECONNECT_ATTEMPTS
|
|
879
1110
|
});
|
|
880
|
-
this.
|
|
1111
|
+
this.client = new RabbitMQClientAdapter(this.config);
|
|
881
1112
|
}
|
|
882
1113
|
/**
|
|
883
1114
|
* Starts the RunMQ instance by establishing a connection to RabbitMQ and initializing necessary components.
|
|
@@ -898,7 +1129,7 @@ var RunMQ = class _RunMQ {
|
|
|
898
1129
|
* @param processor The function that will process the incoming messages
|
|
899
1130
|
*/
|
|
900
1131
|
async process(topic, config, processor) {
|
|
901
|
-
const consumer = new RunMQConsumerCreator(this.
|
|
1132
|
+
const consumer = new RunMQConsumerCreator(this.client, this.logger, this.config.management);
|
|
902
1133
|
await consumer.createConsumer(new ConsumerConfiguration(topic, config, processor));
|
|
903
1134
|
}
|
|
904
1135
|
/**
|
|
@@ -908,7 +1139,7 @@ var RunMQ = class _RunMQ {
|
|
|
908
1139
|
* @param correlationId (Optional) A unique identifier for correlating messages; if not provided, a new UUID will be generated
|
|
909
1140
|
*/
|
|
910
1141
|
publish(topic, message, correlationId = RunMQUtils.generateUUID()) {
|
|
911
|
-
if (!this.publisher) {
|
|
1142
|
+
if (!this.publisher || !this.defaultChannel) {
|
|
912
1143
|
throw new RunMQException(Exceptions.NOT_INITIALIZED, {});
|
|
913
1144
|
}
|
|
914
1145
|
RunMQUtils.assertRecord(message);
|
|
@@ -931,7 +1162,7 @@ var RunMQ = class _RunMQ {
|
|
|
931
1162
|
*/
|
|
932
1163
|
async disconnect() {
|
|
933
1164
|
try {
|
|
934
|
-
await this.
|
|
1165
|
+
await this.client.disconnect();
|
|
935
1166
|
} catch (error) {
|
|
936
1167
|
throw new RunMQException(
|
|
937
1168
|
Exceptions.CONNECTION_NOT_ESTABLISHED,
|
|
@@ -945,19 +1176,20 @@ var RunMQ = class _RunMQ {
|
|
|
945
1176
|
* Checks if the connection is currently active.
|
|
946
1177
|
*/
|
|
947
1178
|
isActive() {
|
|
948
|
-
return this.
|
|
1179
|
+
return this.client.isActive();
|
|
949
1180
|
}
|
|
950
1181
|
async connectWithRetry() {
|
|
951
1182
|
const maxAttempts = this.config.maxReconnectAttempts;
|
|
952
1183
|
const delay = this.config.reconnectDelay;
|
|
953
1184
|
while (this.retryAttempts < maxAttempts) {
|
|
954
1185
|
try {
|
|
955
|
-
await this.
|
|
1186
|
+
await this.client.connect();
|
|
956
1187
|
this.logger.log("Successfully connected to RabbitMQ");
|
|
957
1188
|
this.retryAttempts = 0;
|
|
958
1189
|
return;
|
|
959
1190
|
} catch (error) {
|
|
960
1191
|
this.retryAttempts++;
|
|
1192
|
+
console.log(this.logger);
|
|
961
1193
|
this.logger.error(`Connection attempt ${this.retryAttempts}/${maxAttempts} failed:`, error);
|
|
962
1194
|
if (this.retryAttempts >= maxAttempts) {
|
|
963
1195
|
throw new RunMQException(
|
|
@@ -974,7 +1206,7 @@ var RunMQ = class _RunMQ {
|
|
|
974
1206
|
}
|
|
975
1207
|
}
|
|
976
1208
|
async initialize() {
|
|
977
|
-
this.defaultChannel = await this.
|
|
1209
|
+
this.defaultChannel = await this.client.getDefaultChannel();
|
|
978
1210
|
await this.defaultChannel.assertExchange(Constants.ROUTER_EXCHANGE_NAME, "direct", { durable: true });
|
|
979
1211
|
await this.defaultChannel.assertExchange(Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME, "direct", { durable: true });
|
|
980
1212
|
this.publisher = new RunMQPublisherCreator(this.logger).createPublisher();
|