runmq 1.3.0 → 1.4.2
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 +20 -2
- package/dist/index.cjs +376 -161
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.js +376 -161
- package/dist/index.js.map +1 -1
- package/package.json +9 -3
package/dist/index.js
CHANGED
|
@@ -27,8 +27,8 @@ var RunMQException = class extends Error {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
// src/core/clients/
|
|
31
|
-
import
|
|
30
|
+
// src/core/clients/AmqplibClientAdapter.ts
|
|
31
|
+
import amqplib from "amqplib";
|
|
32
32
|
|
|
33
33
|
// src/core/exceptions/Exceptions.ts
|
|
34
34
|
var Exceptions = class {
|
|
@@ -40,8 +40,8 @@ Exceptions.INVALID_MESSAGE_FORMAT = "MESSAGE_SHOULD_BE_VALID_RECORD";
|
|
|
40
40
|
Exceptions.UNSUPPORTED_SCHEMA = "UNSUPPORTED_SCHEMA";
|
|
41
41
|
Exceptions.FAILURE_TO_DEFINE_TTL_POLICY = "FAILURE_TO_DEFINE_TTL_POLICY";
|
|
42
42
|
|
|
43
|
-
// src/core/clients/
|
|
44
|
-
var
|
|
43
|
+
// src/core/clients/AmqplibChannel.ts
|
|
44
|
+
var AmqplibChannel = class {
|
|
45
45
|
constructor(channel) {
|
|
46
46
|
this.channel = channel;
|
|
47
47
|
}
|
|
@@ -51,8 +51,7 @@ var RabbitMQClientChannel = class {
|
|
|
51
51
|
if (options == null ? void 0 : options.deadLetterRoutingKey) args["x-dead-letter-routing-key"] = options.deadLetterRoutingKey;
|
|
52
52
|
if (options == null ? void 0 : options.messageTtl) args["x-message-ttl"] = options.messageTtl;
|
|
53
53
|
if (options == null ? void 0 : options.arguments) Object.assign(args, options.arguments);
|
|
54
|
-
const result = await this.channel.
|
|
55
|
-
queue,
|
|
54
|
+
const result = await this.channel.assertQueue(queue, {
|
|
56
55
|
durable: options == null ? void 0 : options.durable,
|
|
57
56
|
exclusive: options == null ? void 0 : options.exclusive,
|
|
58
57
|
autoDelete: options == null ? void 0 : options.autoDelete,
|
|
@@ -65,10 +64,7 @@ var RabbitMQClientChannel = class {
|
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
66
|
async checkQueue(queue) {
|
|
68
|
-
const result = await this.channel.
|
|
69
|
-
queue,
|
|
70
|
-
passive: true
|
|
71
|
-
});
|
|
67
|
+
const result = await this.channel.checkQueue(queue);
|
|
72
68
|
return {
|
|
73
69
|
queue: result.queue,
|
|
74
70
|
messageCount: result.messageCount,
|
|
@@ -76,8 +72,7 @@ var RabbitMQClientChannel = class {
|
|
|
76
72
|
};
|
|
77
73
|
}
|
|
78
74
|
async deleteQueue(queue, options) {
|
|
79
|
-
const result = await this.channel.
|
|
80
|
-
queue,
|
|
75
|
+
const result = await this.channel.deleteQueue(queue, {
|
|
81
76
|
ifUnused: options == null ? void 0 : options.ifUnused,
|
|
82
77
|
ifEmpty: options == null ? void 0 : options.ifEmpty
|
|
83
78
|
});
|
|
@@ -89,9 +84,7 @@ var RabbitMQClientChannel = class {
|
|
|
89
84
|
const args = {};
|
|
90
85
|
if (options == null ? void 0 : options.alternateExchange) args["alternate-exchange"] = options.alternateExchange;
|
|
91
86
|
if (options == null ? void 0 : options.arguments) Object.assign(args, options.arguments);
|
|
92
|
-
await this.channel.
|
|
93
|
-
exchange,
|
|
94
|
-
type,
|
|
87
|
+
await this.channel.assertExchange(exchange, type, {
|
|
95
88
|
durable: options == null ? void 0 : options.durable,
|
|
96
89
|
internal: options == null ? void 0 : options.internal,
|
|
97
90
|
autoDelete: options == null ? void 0 : options.autoDelete,
|
|
@@ -102,37 +95,26 @@ var RabbitMQClientChannel = class {
|
|
|
102
95
|
};
|
|
103
96
|
}
|
|
104
97
|
async checkExchange(exchange) {
|
|
105
|
-
await this.channel.
|
|
106
|
-
exchange,
|
|
107
|
-
passive: true
|
|
108
|
-
});
|
|
98
|
+
await this.channel.checkExchange(exchange);
|
|
109
99
|
return {
|
|
110
100
|
exchange
|
|
111
101
|
};
|
|
112
102
|
}
|
|
113
103
|
async deleteExchange(exchange, options) {
|
|
114
|
-
await this.channel.
|
|
115
|
-
exchange,
|
|
104
|
+
await this.channel.deleteExchange(exchange, {
|
|
116
105
|
ifUnused: options == null ? void 0 : options.ifUnused
|
|
117
106
|
});
|
|
118
107
|
}
|
|
119
108
|
async bindQueue(queue, source, pattern, args) {
|
|
120
|
-
await this.channel.
|
|
121
|
-
queue,
|
|
122
|
-
exchange: source,
|
|
123
|
-
routingKey: pattern,
|
|
124
|
-
arguments: args
|
|
125
|
-
});
|
|
109
|
+
await this.channel.bindQueue(queue, source, pattern, args);
|
|
126
110
|
}
|
|
127
111
|
publish(exchange, routingKey, content, options) {
|
|
128
112
|
var _a2;
|
|
129
|
-
this.channel.
|
|
130
|
-
exchange,
|
|
131
|
-
routingKey,
|
|
113
|
+
return this.channel.publish(exchange, routingKey, content, {
|
|
132
114
|
correlationId: options == null ? void 0 : options.correlationId,
|
|
133
115
|
messageId: options == null ? void 0 : options.messageId,
|
|
134
116
|
headers: options == null ? void 0 : options.headers,
|
|
135
|
-
|
|
117
|
+
persistent: options == null ? void 0 : options.persistent,
|
|
136
118
|
expiration: (_a2 = options == null ? void 0 : options.expiration) == null ? void 0 : _a2.toString(),
|
|
137
119
|
contentType: options == null ? void 0 : options.contentType,
|
|
138
120
|
contentEncoding: options == null ? void 0 : options.contentEncoding,
|
|
@@ -142,79 +124,106 @@ var RabbitMQClientChannel = class {
|
|
|
142
124
|
type: options == null ? void 0 : options.type,
|
|
143
125
|
userId: options == null ? void 0 : options.userId,
|
|
144
126
|
appId: options == null ? void 0 : options.appId
|
|
145
|
-
}
|
|
146
|
-
return true;
|
|
127
|
+
});
|
|
147
128
|
}
|
|
148
129
|
async consume(queue, onMessage, options) {
|
|
149
|
-
const result = await this.channel.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
exclusive: options == null ? void 0 : options.exclusive,
|
|
155
|
-
arguments: options == null ? void 0 : options.arguments
|
|
156
|
-
}, (msg) => {
|
|
157
|
-
const body = msg.body;
|
|
158
|
-
const content = Buffer.isBuffer(body) ? body : typeof body === "string" ? Buffer.from(body) : Buffer.from(JSON.stringify(body));
|
|
130
|
+
const result = await this.channel.consume(queue, (msg) => {
|
|
131
|
+
if (msg === null) {
|
|
132
|
+
onMessage(null);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
159
135
|
const consumeMessage = {
|
|
160
|
-
content,
|
|
136
|
+
content: msg.content,
|
|
161
137
|
fields: {
|
|
162
|
-
consumerTag: msg.consumerTag,
|
|
163
|
-
deliveryTag: msg.deliveryTag,
|
|
164
|
-
redelivered: msg.redelivered,
|
|
165
|
-
exchange: msg.exchange,
|
|
166
|
-
routingKey: msg.routingKey
|
|
138
|
+
consumerTag: msg.fields.consumerTag,
|
|
139
|
+
deliveryTag: msg.fields.deliveryTag,
|
|
140
|
+
redelivered: msg.fields.redelivered,
|
|
141
|
+
exchange: msg.fields.exchange,
|
|
142
|
+
routingKey: msg.fields.routingKey
|
|
167
143
|
},
|
|
168
144
|
properties: {
|
|
169
|
-
contentType: msg.contentType,
|
|
170
|
-
contentEncoding: msg.contentEncoding,
|
|
171
|
-
headers: msg.headers || {},
|
|
172
|
-
deliveryMode: msg.
|
|
173
|
-
priority: msg.priority,
|
|
174
|
-
correlationId: msg.correlationId,
|
|
175
|
-
replyTo: msg.replyTo,
|
|
176
|
-
expiration: msg.expiration,
|
|
177
|
-
messageId: msg.messageId,
|
|
178
|
-
timestamp: msg.timestamp,
|
|
179
|
-
type: msg.type,
|
|
180
|
-
userId: msg.userId,
|
|
181
|
-
appId: msg.appId
|
|
145
|
+
contentType: msg.properties.contentType || void 0,
|
|
146
|
+
contentEncoding: msg.properties.contentEncoding || void 0,
|
|
147
|
+
headers: msg.properties.headers || {},
|
|
148
|
+
deliveryMode: msg.properties.deliveryMode,
|
|
149
|
+
priority: msg.properties.priority,
|
|
150
|
+
correlationId: msg.properties.correlationId || void 0,
|
|
151
|
+
replyTo: msg.properties.replyTo || void 0,
|
|
152
|
+
expiration: msg.properties.expiration || void 0,
|
|
153
|
+
messageId: msg.properties.messageId || void 0,
|
|
154
|
+
timestamp: msg.properties.timestamp,
|
|
155
|
+
type: msg.properties.type || void 0,
|
|
156
|
+
userId: msg.properties.userId || void 0,
|
|
157
|
+
appId: msg.properties.appId || void 0
|
|
182
158
|
}
|
|
183
159
|
};
|
|
184
160
|
onMessage(consumeMessage);
|
|
161
|
+
}, {
|
|
162
|
+
consumerTag: options == null ? void 0 : options.consumerTag,
|
|
163
|
+
noLocal: options == null ? void 0 : options.noLocal,
|
|
164
|
+
noAck: options == null ? void 0 : options.noAck,
|
|
165
|
+
exclusive: options == null ? void 0 : options.exclusive,
|
|
166
|
+
priority: options == null ? void 0 : options.priority,
|
|
167
|
+
arguments: options == null ? void 0 : options.arguments
|
|
185
168
|
});
|
|
186
169
|
return {
|
|
187
170
|
consumerTag: result.consumerTag
|
|
188
171
|
};
|
|
189
172
|
}
|
|
190
173
|
ack(message, allUpTo) {
|
|
191
|
-
this.channel.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
174
|
+
this.channel.ack(
|
|
175
|
+
{ fields: message.fields, content: message.content, properties: message.properties },
|
|
176
|
+
allUpTo
|
|
177
|
+
);
|
|
195
178
|
}
|
|
196
179
|
nack(message, allUpTo, requeue) {
|
|
197
|
-
this.channel.
|
|
198
|
-
|
|
199
|
-
|
|
180
|
+
this.channel.nack(
|
|
181
|
+
{ fields: message.fields, content: message.content, properties: message.properties },
|
|
182
|
+
allUpTo,
|
|
200
183
|
requeue
|
|
201
|
-
|
|
184
|
+
);
|
|
202
185
|
}
|
|
203
186
|
async prefetch(count, global) {
|
|
204
|
-
await this.channel.
|
|
205
|
-
prefetchCount: count,
|
|
206
|
-
global
|
|
207
|
-
});
|
|
187
|
+
await this.channel.prefetch(count, global);
|
|
208
188
|
}
|
|
209
189
|
async close() {
|
|
210
190
|
await this.channel.close();
|
|
211
191
|
}
|
|
212
192
|
};
|
|
213
193
|
|
|
214
|
-
// src/core/
|
|
215
|
-
var
|
|
216
|
-
constructor(
|
|
194
|
+
// src/core/logging/RunMQConsoleLogger.ts
|
|
195
|
+
var RunMQConsoleLogger = class {
|
|
196
|
+
constructor() {
|
|
197
|
+
this.prefix = "[RunMQ] - ";
|
|
198
|
+
}
|
|
199
|
+
log(message) {
|
|
200
|
+
console.log(this.formatMessage(message));
|
|
201
|
+
}
|
|
202
|
+
error(message, ...optionalParams) {
|
|
203
|
+
console.error(this.formatMessage(message), ...optionalParams);
|
|
204
|
+
}
|
|
205
|
+
warn(message, ...optionalParams) {
|
|
206
|
+
console.warn(this.formatMessage(message), ...optionalParams);
|
|
207
|
+
}
|
|
208
|
+
info(message, ...optionalParams) {
|
|
209
|
+
console.info(this.formatMessage(message), ...optionalParams);
|
|
210
|
+
}
|
|
211
|
+
debug(message, ...optionalParams) {
|
|
212
|
+
console.debug(this.formatMessage(message), ...optionalParams);
|
|
213
|
+
}
|
|
214
|
+
verbose(message, ...optionalParams) {
|
|
215
|
+
console.debug(this.formatMessage(message), ...optionalParams);
|
|
216
|
+
}
|
|
217
|
+
formatMessage(message) {
|
|
218
|
+
return `${this.prefix} ${message}`;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// src/core/clients/AmqplibClientAdapter.ts
|
|
223
|
+
var AmqplibClientAdapter = class {
|
|
224
|
+
constructor(config, logger = new RunMQConsoleLogger()) {
|
|
217
225
|
this.config = config;
|
|
226
|
+
this.logger = logger;
|
|
218
227
|
this.isConnected = false;
|
|
219
228
|
this.acquiredChannels = [];
|
|
220
229
|
}
|
|
@@ -230,38 +239,20 @@ var RabbitMQClientAdapter = class {
|
|
|
230
239
|
}
|
|
231
240
|
this.connection = void 0;
|
|
232
241
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
// Disable automatic retries - we handle retries at RunMQ level
|
|
236
|
-
retryLow: 100,
|
|
237
|
-
retryHigh: 200,
|
|
238
|
-
connectionTimeout: 5e3
|
|
239
|
-
});
|
|
242
|
+
const connection = await amqplib.connect(this.config.url);
|
|
243
|
+
this.connection = connection;
|
|
240
244
|
this.connection.on("error", (err) => {
|
|
241
|
-
|
|
245
|
+
this.logger.error("RabbitMQ connection error:", { error: err });
|
|
242
246
|
this.isConnected = false;
|
|
243
247
|
});
|
|
244
|
-
this.connection.on("
|
|
245
|
-
this.isConnected =
|
|
246
|
-
});
|
|
247
|
-
this.connection.on("connection.blocked", (reason) => {
|
|
248
|
-
console.warn("RabbitMQ connection blocked:", reason);
|
|
249
|
-
});
|
|
250
|
-
this.connection.on("connection.unblocked", () => {
|
|
251
|
-
console.info("RabbitMQ connection unblocked");
|
|
248
|
+
this.connection.on("close", () => {
|
|
249
|
+
this.isConnected = false;
|
|
252
250
|
});
|
|
253
|
-
await this.connection.onConnect(5e3, true);
|
|
254
251
|
this.isConnected = true;
|
|
255
252
|
return this.connection;
|
|
256
253
|
} catch (error) {
|
|
257
254
|
this.isConnected = false;
|
|
258
|
-
|
|
259
|
-
try {
|
|
260
|
-
this.connection.close();
|
|
261
|
-
} catch (e) {
|
|
262
|
-
}
|
|
263
|
-
this.connection = void 0;
|
|
264
|
-
}
|
|
255
|
+
this.connection = void 0;
|
|
265
256
|
throw new RunMQException(
|
|
266
257
|
Exceptions.CONNECTION_NOT_ESTABLISHED,
|
|
267
258
|
{
|
|
@@ -272,9 +263,9 @@ var RabbitMQClientAdapter = class {
|
|
|
272
263
|
}
|
|
273
264
|
async getChannel() {
|
|
274
265
|
const connection = await this.connect();
|
|
275
|
-
const rawChannel = await connection.
|
|
266
|
+
const rawChannel = await connection.createChannel();
|
|
276
267
|
this.acquiredChannels.push(rawChannel);
|
|
277
|
-
return new
|
|
268
|
+
return new AmqplibChannel(rawChannel);
|
|
278
269
|
}
|
|
279
270
|
async getDefaultChannel() {
|
|
280
271
|
if (!this.defaultChannel) {
|
|
@@ -291,9 +282,7 @@ var RabbitMQClientAdapter = class {
|
|
|
291
282
|
this.acquiredChannels = [];
|
|
292
283
|
for (const channel of channels) {
|
|
293
284
|
try {
|
|
294
|
-
|
|
295
|
-
await channel.close();
|
|
296
|
-
}
|
|
285
|
+
await channel.close();
|
|
297
286
|
} catch (e) {
|
|
298
287
|
}
|
|
299
288
|
}
|
|
@@ -335,7 +324,8 @@ var Constants = {
|
|
|
335
324
|
DEAD_LETTER_ROUTER_EXCHANGE_NAME: RUNMQ_PREFIX + "dead_letter_router",
|
|
336
325
|
RETRY_DELAY_QUEUE_PREFIX: RUNMQ_PREFIX + "retry_delay_",
|
|
337
326
|
DLQ_QUEUE_PREFIX: RUNMQ_PREFIX + "dlq_",
|
|
338
|
-
MESSAGE_TTL_OPERATOR_POLICY_PREFIX: RUNMQ_PREFIX + "message_ttl_operator_policy"
|
|
327
|
+
MESSAGE_TTL_OPERATOR_POLICY_PREFIX: RUNMQ_PREFIX + "message_ttl_operator_policy",
|
|
328
|
+
METADATA_STORE_PREFIX: RUNMQ_PREFIX + "metadata_"
|
|
339
329
|
};
|
|
340
330
|
var DEFAULTS = {
|
|
341
331
|
RECONNECT_DELAY: 5e3,
|
|
@@ -413,6 +403,27 @@ var RunMQFailedMessageRejecterProcessor = class {
|
|
|
413
403
|
}
|
|
414
404
|
};
|
|
415
405
|
|
|
406
|
+
// src/core/message/RunMQMessage.ts
|
|
407
|
+
var RunMQMessage = class {
|
|
408
|
+
static isValid(obj) {
|
|
409
|
+
if (typeof obj === "object" && obj !== null) {
|
|
410
|
+
return "message" in obj && "meta" in obj && typeof obj.message === "object" && obj.message !== null && Array.isArray(obj.message) === false && typeof obj.meta === "object" && obj.meta !== null && "id" in obj.meta && "correlationId" in obj.meta && "publishedAt" in obj.meta && typeof obj.meta.id === "string" && typeof obj.meta.correlationId === "string" && typeof obj.meta.publishedAt === "number";
|
|
411
|
+
}
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
constructor(message, meta) {
|
|
415
|
+
this.message = message;
|
|
416
|
+
this.meta = meta;
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
var RunMQMessageMeta = class {
|
|
420
|
+
constructor(id, publishedAt, correlationId) {
|
|
421
|
+
this.id = id;
|
|
422
|
+
this.correlationId = correlationId;
|
|
423
|
+
this.publishedAt = publishedAt;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
416
427
|
// src/core/consumer/ConsumerCreatorUtils.ts
|
|
417
428
|
var ConsumerCreatorUtils = class {
|
|
418
429
|
static getDLQTopicName(topic) {
|
|
@@ -464,7 +475,28 @@ var RunMQRetriesCheckerProcessor = class {
|
|
|
464
475
|
);
|
|
465
476
|
}
|
|
466
477
|
moveToFinalDeadLetter(message) {
|
|
467
|
-
this.
|
|
478
|
+
const originalPayload = this.extractOriginalPayload(message);
|
|
479
|
+
const dlqMessage = new RabbitMQMessage(
|
|
480
|
+
originalPayload,
|
|
481
|
+
message.id,
|
|
482
|
+
message.correlationId,
|
|
483
|
+
message.channel,
|
|
484
|
+
message.amqpMessage,
|
|
485
|
+
message.headers
|
|
486
|
+
);
|
|
487
|
+
this.DLQPublisher.publish(ConsumerCreatorUtils.getDLQTopicName(this.config.name), dlqMessage);
|
|
488
|
+
}
|
|
489
|
+
extractOriginalPayload(message) {
|
|
490
|
+
if (typeof message.message === "string") {
|
|
491
|
+
try {
|
|
492
|
+
const parsed = JSON.parse(message.message);
|
|
493
|
+
if (RunMQMessage.isValid(parsed)) {
|
|
494
|
+
return parsed.message;
|
|
495
|
+
}
|
|
496
|
+
} catch (e) {
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return message.message;
|
|
468
500
|
}
|
|
469
501
|
acknowledgeMessage(message) {
|
|
470
502
|
try {
|
|
@@ -542,27 +574,6 @@ var RunMQExceptionLoggerProcessor = class {
|
|
|
542
574
|
}
|
|
543
575
|
};
|
|
544
576
|
|
|
545
|
-
// src/core/message/RunMQMessage.ts
|
|
546
|
-
var RunMQMessage = class {
|
|
547
|
-
static isValid(obj) {
|
|
548
|
-
if (typeof obj === "object" && obj !== null) {
|
|
549
|
-
return "message" in obj && "meta" in obj && typeof obj.message === "object" && obj.message !== null && Array.isArray(obj.message) === false && typeof obj.meta === "object" && obj.meta !== null && "id" in obj.meta && "correlationId" in obj.meta && "publishedAt" in obj.meta && typeof obj.meta.id === "string" && typeof obj.meta.correlationId === "string" && typeof obj.meta.publishedAt === "number";
|
|
550
|
-
}
|
|
551
|
-
return false;
|
|
552
|
-
}
|
|
553
|
-
constructor(message, meta) {
|
|
554
|
-
this.message = message;
|
|
555
|
-
this.meta = meta;
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
var RunMQMessageMeta = class {
|
|
559
|
-
constructor(id, publishedAt, correlationId) {
|
|
560
|
-
this.id = id;
|
|
561
|
-
this.correlationId = correlationId;
|
|
562
|
-
this.publishedAt = publishedAt;
|
|
563
|
-
}
|
|
564
|
-
};
|
|
565
|
-
|
|
566
577
|
// src/core/serializers/deserializer/validation/AjvSchemaValidator.ts
|
|
567
578
|
import Ajv from "ajv";
|
|
568
579
|
var AjvSchemaValidator = class {
|
|
@@ -837,6 +848,91 @@ var RabbitMQManagementClient = class {
|
|
|
837
848
|
return false;
|
|
838
849
|
}
|
|
839
850
|
}
|
|
851
|
+
/**
|
|
852
|
+
* Creates or updates a RabbitMQ parameter.
|
|
853
|
+
* Parameters are custom key-value stores that can hold any JSON data.
|
|
854
|
+
*
|
|
855
|
+
* @param name - The parameter name
|
|
856
|
+
* @param value - The parameter value (any JSON-serializable object)
|
|
857
|
+
*/
|
|
858
|
+
async setParameter(name, value) {
|
|
859
|
+
try {
|
|
860
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
861
|
+
const response = await fetch(url, {
|
|
862
|
+
method: "PUT",
|
|
863
|
+
headers: {
|
|
864
|
+
"Content-Type": "application/json",
|
|
865
|
+
"Authorization": this.getAuthHeader()
|
|
866
|
+
},
|
|
867
|
+
body: JSON.stringify({ value })
|
|
868
|
+
});
|
|
869
|
+
if (!response.ok) {
|
|
870
|
+
const error = await response.text();
|
|
871
|
+
this.logger.error(`Failed to set parameter ${name}: ${response.status} - ${error}`);
|
|
872
|
+
return false;
|
|
873
|
+
}
|
|
874
|
+
this.logger.info(`Successfully set parameter: ${name}`);
|
|
875
|
+
return true;
|
|
876
|
+
} catch (error) {
|
|
877
|
+
this.logger.error(`Error setting parameter: ${error}`);
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Gets a RabbitMQ parameter.
|
|
883
|
+
*
|
|
884
|
+
* @param name - The parameter name
|
|
885
|
+
*/
|
|
886
|
+
async getParameter(name) {
|
|
887
|
+
try {
|
|
888
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
889
|
+
const response = await fetch(url, {
|
|
890
|
+
method: "GET",
|
|
891
|
+
headers: {
|
|
892
|
+
"Authorization": this.getAuthHeader()
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
if (!response.ok) {
|
|
896
|
+
if (response.status === 404) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
const error = await response.text();
|
|
900
|
+
this.logger.error(`Failed to get parameter ${name}: ${response.status} - ${error}`);
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
const data = await response.json();
|
|
904
|
+
return data.value;
|
|
905
|
+
} catch (error) {
|
|
906
|
+
this.logger.error(`Error getting parameter: ${error}`);
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Deletes a RabbitMQ parameter.
|
|
912
|
+
*
|
|
913
|
+
* @param name - The parameter name
|
|
914
|
+
*/
|
|
915
|
+
async deleteParameter(name) {
|
|
916
|
+
try {
|
|
917
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
918
|
+
const response = await fetch(url, {
|
|
919
|
+
method: "DELETE",
|
|
920
|
+
headers: {
|
|
921
|
+
"Authorization": this.getAuthHeader()
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
if (!response.ok && response.status !== 404) {
|
|
925
|
+
const error = await response.text();
|
|
926
|
+
this.logger.error(`Failed to delete parameter ${name}: ${response.status} - ${error}`);
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
this.logger.info(`Successfully deleted parameter: ${name}`);
|
|
930
|
+
return true;
|
|
931
|
+
} catch (error) {
|
|
932
|
+
this.logger.error(`Error deleting parameter: ${error}`);
|
|
933
|
+
return false;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
840
936
|
};
|
|
841
937
|
|
|
842
938
|
// src/core/management/Policies/RabbitMQMessageTTLPolicy.ts
|
|
@@ -866,6 +962,9 @@ var RunMQTTLPolicyManager = class {
|
|
|
866
962
|
}
|
|
867
963
|
}
|
|
868
964
|
async initialize() {
|
|
965
|
+
if (this.isManagementPluginEnabled) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
869
968
|
if (!this.managementClient) {
|
|
870
969
|
this.logger.warn("Management client not configured");
|
|
871
970
|
return;
|
|
@@ -898,21 +997,166 @@ var RunMQTTLPolicyManager = class {
|
|
|
898
997
|
}
|
|
899
998
|
};
|
|
900
999
|
|
|
1000
|
+
// src/core/management/Policies/RunMQQueueMetadata.ts
|
|
1001
|
+
var METADATA_SCHEMA_VERSION = 0;
|
|
1002
|
+
|
|
1003
|
+
// src/core/management/Policies/RabbitMQMetadata.ts
|
|
1004
|
+
var RabbitMQMetadata = class {
|
|
1005
|
+
/**
|
|
1006
|
+
* Creates metadata for a queue.
|
|
1007
|
+
* @param maxRetries - Maximum retry attempts configured for the queue
|
|
1008
|
+
* @param existingMetadata - Optional existing metadata to preserve createdAt
|
|
1009
|
+
* @returns RunMQQueueMetadata object
|
|
1010
|
+
*/
|
|
1011
|
+
static createMetadataFor(maxRetries, existingMetadata) {
|
|
1012
|
+
var _a2;
|
|
1013
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1014
|
+
return __spreadValues({
|
|
1015
|
+
version: METADATA_SCHEMA_VERSION,
|
|
1016
|
+
maxRetries,
|
|
1017
|
+
createdAt: (_a2 = existingMetadata == null ? void 0 : existingMetadata.createdAt) != null ? _a2 : now
|
|
1018
|
+
}, existingMetadata ? { updatedAt: now } : {});
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Gets the parameter name for a given queue.
|
|
1022
|
+
*/
|
|
1023
|
+
static getParameterName(queueName) {
|
|
1024
|
+
return Constants.METADATA_STORE_PREFIX + queueName;
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
// src/core/management/Policies/RunMQMetadataManager.ts
|
|
1029
|
+
var RunMQMetadataManager = class {
|
|
1030
|
+
constructor(logger, managementConfig) {
|
|
1031
|
+
this.logger = logger;
|
|
1032
|
+
this.managementConfig = managementConfig;
|
|
1033
|
+
this.managementClient = null;
|
|
1034
|
+
this.isManagementPluginEnabled = false;
|
|
1035
|
+
if (this.managementConfig) {
|
|
1036
|
+
this.managementClient = new RabbitMQManagementClient(this.managementConfig, this.logger);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Initialize the manager by checking if management plugin is available.
|
|
1041
|
+
*/
|
|
1042
|
+
async initialize() {
|
|
1043
|
+
if (this.isManagementPluginEnabled) {
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
if (!this.managementClient) {
|
|
1047
|
+
this.logger.warn("Management client not configured - metadata storage disabled");
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
this.isManagementPluginEnabled = await this.managementClient.checkManagementPluginEnabled();
|
|
1051
|
+
if (!this.isManagementPluginEnabled) {
|
|
1052
|
+
this.logger.warn("RabbitMQ management plugin is not enabled - metadata storage disabled");
|
|
1053
|
+
} else {
|
|
1054
|
+
this.logger.info("RunMQ metadata storage initialized");
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Store or update metadata for a queue.
|
|
1059
|
+
* If metadata already exists, preserves createdAt and sets updatedAt.
|
|
1060
|
+
*
|
|
1061
|
+
* @param queueName - The name of the queue
|
|
1062
|
+
* @param maxRetries - Maximum retry attempts
|
|
1063
|
+
* @returns true if metadata was stored successfully, false otherwise
|
|
1064
|
+
*/
|
|
1065
|
+
async apply(queueName, maxRetries) {
|
|
1066
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1067
|
+
this.logger.warn(`Cannot store metadata for queue '${queueName}' - management plugin not available`);
|
|
1068
|
+
return false;
|
|
1069
|
+
}
|
|
1070
|
+
try {
|
|
1071
|
+
const existingMetadata = await this.getMetadata(queueName);
|
|
1072
|
+
const metadata = RabbitMQMetadata.createMetadataFor(
|
|
1073
|
+
maxRetries,
|
|
1074
|
+
existingMetadata != null ? existingMetadata : void 0
|
|
1075
|
+
);
|
|
1076
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1077
|
+
const success = await this.managementClient.setParameter(
|
|
1078
|
+
paramName,
|
|
1079
|
+
metadata
|
|
1080
|
+
);
|
|
1081
|
+
if (success) {
|
|
1082
|
+
const action = existingMetadata ? "Updated" : "Created";
|
|
1083
|
+
this.logger.info(`${action} metadata for queue: ${queueName}`);
|
|
1084
|
+
return true;
|
|
1085
|
+
}
|
|
1086
|
+
this.logger.error(`Failed to store metadata for queue: ${queueName}`);
|
|
1087
|
+
return false;
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
this.logger.error(`Error storing metadata for queue ${queueName}: ${error}`);
|
|
1090
|
+
return false;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Get metadata for a queue.
|
|
1095
|
+
*
|
|
1096
|
+
* @param queueName - The name of the queue
|
|
1097
|
+
* @returns The queue metadata or null if not found
|
|
1098
|
+
*/
|
|
1099
|
+
async getMetadata(queueName) {
|
|
1100
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
try {
|
|
1104
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1105
|
+
return await this.managementClient.getParameter(
|
|
1106
|
+
paramName
|
|
1107
|
+
);
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
this.logger.warn(`Failed to get metadata for queue ${queueName}: ${error}`);
|
|
1110
|
+
return null;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Delete metadata for a queue.
|
|
1115
|
+
*
|
|
1116
|
+
* @param queueName - The name of the queue
|
|
1117
|
+
*/
|
|
1118
|
+
async cleanup(queueName) {
|
|
1119
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1123
|
+
await this.managementClient.deleteParameter(paramName);
|
|
1124
|
+
this.logger.info(`Deleted metadata for queue: ${queueName}`);
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Check if management plugin is enabled and metadata storage is available.
|
|
1128
|
+
*/
|
|
1129
|
+
isEnabled() {
|
|
1130
|
+
return this.isManagementPluginEnabled;
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
|
|
901
1134
|
// src/core/consumer/RunMQConsumerCreator.ts
|
|
902
1135
|
var RunMQConsumerCreator = class {
|
|
903
1136
|
constructor(client, logger, managementConfig) {
|
|
904
1137
|
this.client = client;
|
|
905
1138
|
this.logger = logger;
|
|
906
1139
|
this.ttlPolicyManager = new RunMQTTLPolicyManager(logger, managementConfig);
|
|
1140
|
+
this.metadataManager = new RunMQMetadataManager(logger, managementConfig);
|
|
907
1141
|
}
|
|
908
1142
|
async createConsumer(consumerConfiguration) {
|
|
909
1143
|
await this.ttlPolicyManager.initialize();
|
|
1144
|
+
await this.metadataManager.initialize();
|
|
910
1145
|
await this.assertQueues(consumerConfiguration);
|
|
911
1146
|
await this.bindQueues(consumerConfiguration);
|
|
1147
|
+
await this.storeMetadata(consumerConfiguration);
|
|
912
1148
|
for (let i = 0; i < consumerConfiguration.processorConfig.consumersCount; i++) {
|
|
913
1149
|
await this.runProcessor(consumerConfiguration);
|
|
914
1150
|
}
|
|
915
1151
|
}
|
|
1152
|
+
async storeMetadata(consumerConfiguration) {
|
|
1153
|
+
var _a2;
|
|
1154
|
+
const maxRetries = (_a2 = consumerConfiguration.processorConfig.attempts) != null ? _a2 : DEFAULTS.PROCESSING_ATTEMPTS;
|
|
1155
|
+
await this.metadataManager.apply(
|
|
1156
|
+
consumerConfiguration.processorConfig.name,
|
|
1157
|
+
maxRetries
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
916
1160
|
async runProcessor(consumerConfiguration) {
|
|
917
1161
|
const consumerChannel = await this.getProcessorChannel();
|
|
918
1162
|
const DLQPublisher = new RunMQPublisherCreator(this.logger).createPublisher(Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME);
|
|
@@ -1029,34 +1273,6 @@ var ConsumerConfiguration = class {
|
|
|
1029
1273
|
}
|
|
1030
1274
|
};
|
|
1031
1275
|
|
|
1032
|
-
// src/core/logging/RunMQConsoleLogger.ts
|
|
1033
|
-
var RunMQConsoleLogger = class {
|
|
1034
|
-
constructor() {
|
|
1035
|
-
this.prefix = "[RunMQ] - ";
|
|
1036
|
-
}
|
|
1037
|
-
log(message) {
|
|
1038
|
-
console.log(this.formatMessage(message));
|
|
1039
|
-
}
|
|
1040
|
-
error(message, ...optionalParams) {
|
|
1041
|
-
console.error(this.formatMessage(message), ...optionalParams);
|
|
1042
|
-
}
|
|
1043
|
-
warn(message, ...optionalParams) {
|
|
1044
|
-
console.warn(this.formatMessage(message), ...optionalParams);
|
|
1045
|
-
}
|
|
1046
|
-
info(message, ...optionalParams) {
|
|
1047
|
-
console.info(this.formatMessage(message), ...optionalParams);
|
|
1048
|
-
}
|
|
1049
|
-
debug(message, ...optionalParams) {
|
|
1050
|
-
console.debug(this.formatMessage(message), ...optionalParams);
|
|
1051
|
-
}
|
|
1052
|
-
verbose(message, ...optionalParams) {
|
|
1053
|
-
console.debug(this.formatMessage(message), ...optionalParams);
|
|
1054
|
-
}
|
|
1055
|
-
formatMessage(message) {
|
|
1056
|
-
return `${this.prefix} ${message}`;
|
|
1057
|
-
}
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
1276
|
// src/core/message/RabbitMQMessageProperties.ts
|
|
1061
1277
|
var RabbitMQMessageProperties = class {
|
|
1062
1278
|
constructor(id, correlationId) {
|
|
@@ -1075,7 +1291,8 @@ var RunMQ = class _RunMQ {
|
|
|
1075
1291
|
reconnectDelay: (_a2 = config.reconnectDelay) != null ? _a2 : DEFAULTS.RECONNECT_DELAY,
|
|
1076
1292
|
maxReconnectAttempts: (_b = config.maxReconnectAttempts) != null ? _b : DEFAULTS.MAX_RECONNECT_ATTEMPTS
|
|
1077
1293
|
});
|
|
1078
|
-
this.client = new
|
|
1294
|
+
this.client = new AmqplibClientAdapter(this.config, this.logger);
|
|
1295
|
+
this.consumer = new RunMQConsumerCreator(this.client, this.logger, this.config.management);
|
|
1079
1296
|
}
|
|
1080
1297
|
/**
|
|
1081
1298
|
* Starts the RunMQ instance by establishing a connection to RabbitMQ and initializing necessary components.
|
|
@@ -1096,8 +1313,7 @@ var RunMQ = class _RunMQ {
|
|
|
1096
1313
|
* @param processor The function that will process the incoming messages
|
|
1097
1314
|
*/
|
|
1098
1315
|
async process(topic, config, processor) {
|
|
1099
|
-
|
|
1100
|
-
await consumer.createConsumer(new ConsumerConfiguration(topic, config, processor));
|
|
1316
|
+
await this.consumer.createConsumer(new ConsumerConfiguration(topic, config, processor));
|
|
1101
1317
|
}
|
|
1102
1318
|
/**
|
|
1103
1319
|
* Publishes a message to the specified topic with an optional correlation ID
|
|
@@ -1156,7 +1372,6 @@ var RunMQ = class _RunMQ {
|
|
|
1156
1372
|
return;
|
|
1157
1373
|
} catch (error) {
|
|
1158
1374
|
this.retryAttempts++;
|
|
1159
|
-
console.log(this.logger);
|
|
1160
1375
|
this.logger.error(`Connection attempt ${this.retryAttempts}/${maxAttempts} failed:`, error);
|
|
1161
1376
|
if (this.retryAttempts >= maxAttempts) {
|
|
1162
1377
|
throw new RunMQException(
|