runmq 1.3.0 → 1.4.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 +20 -2
- package/dist/index.cjs +314 -59
- 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 +314 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,8 +23,9 @@ Whether you’re running <b>background jobs</b>, designing an <b>event-driven ar
|
|
|
23
23
|
- **Isolated Queues per Processor**: Each processor gets its own dedicated queue and DLQ, ensuring full isolation and predictable behavior across services.
|
|
24
24
|
- **Schema Validation**: Optional JSON Schema validation powered by AJV for safer message handling and data integrity.
|
|
25
25
|
- **Concurrent Consumers**: Scale either horizontally (multiple instances) or vertically (multiple consumers per queue, leveraging RabbitMQ prefetch) to maximize throughput and efficiency.
|
|
26
|
-
- **RabbitMQ Durability & Acknowledgements**: Leverages RabbitMQ
|
|
26
|
+
- **RabbitMQ Durability & Acknowledgements**: Leverages RabbitMQ's persistent storage and acknowledgment model to guarantee at-least-once delivery, even across restarts and failures.
|
|
27
27
|
- **Custom Logging**: Plug in your own logger or use the default console logger for full control over message visibility.
|
|
28
|
+
- **Management Dashboard**: A web-based dashboard for real-time monitoring and management of queues, DLQs, and message processing. [Check it out!](https://github.com/runmq/pulse)
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
@@ -212,7 +213,24 @@ RunMQ can leverage RabbitMQ policies to manage the delay between attempts, it's
|
|
|
212
213
|
#### Benefits
|
|
213
214
|
- Flexible and easy management of retry delays
|
|
214
215
|
- Reduces operational overhead
|
|
215
|
-
- Fully compatible with RunMQ
|
|
216
|
+
- Fully compatible with RunMQ's retry and DLQ mechanisms
|
|
217
|
+
|
|
218
|
+
### Queue Metadata Storage
|
|
219
|
+
|
|
220
|
+
RunMQ automatically stores queue metadata (such as max retries and creation timestamp) using RabbitMQ's parameters API. This enables external tools and dashboards to discover RunMQ-managed queues and understand their configuration without direct access to the application code.
|
|
221
|
+
|
|
222
|
+
When a processor is configured, RunMQ creates a metadata parameter that stores:
|
|
223
|
+
- **Version**: Schema version for future-proof migrations.
|
|
224
|
+
- **Max Retries**: The configured retry limit for the queue.
|
|
225
|
+
- **Created At**: ISO 8601 timestamp when the queue was first configured.
|
|
226
|
+
- **Updated At**: ISO 8601 timestamp when the configuration was last changed (if applicable).
|
|
227
|
+
|
|
228
|
+
#### Benefits
|
|
229
|
+
- **Dashboard Integration**: External monitoring tools and dashboards can query RabbitMQ's management API to retrieve queue metadata and display topology information (e.g., "10 retries with 5s delay, then to DLQ").
|
|
230
|
+
- **Self-Documenting Queues**: Queue configurations are discoverable directly from RabbitMQ, without needing access to application source code.
|
|
231
|
+
- **Automatic Updates**: When processor configuration changes, metadata is automatically updated while preserving the original creation timestamp.
|
|
232
|
+
|
|
233
|
+
> **Note**: This feature requires RabbitMQ Management Plugin to be enabled for external tools to query the metadata parameters and for the parameters to be set.
|
|
216
234
|
|
|
217
235
|
### Custom Logger
|
|
218
236
|
|
package/dist/index.cjs
CHANGED
|
@@ -244,10 +244,39 @@ var RabbitMQClientChannel = class {
|
|
|
244
244
|
}
|
|
245
245
|
};
|
|
246
246
|
|
|
247
|
+
// src/core/logging/RunMQConsoleLogger.ts
|
|
248
|
+
var RunMQConsoleLogger = class {
|
|
249
|
+
constructor() {
|
|
250
|
+
this.prefix = "[RunMQ] - ";
|
|
251
|
+
}
|
|
252
|
+
log(message) {
|
|
253
|
+
console.log(this.formatMessage(message));
|
|
254
|
+
}
|
|
255
|
+
error(message, ...optionalParams) {
|
|
256
|
+
console.error(this.formatMessage(message), ...optionalParams);
|
|
257
|
+
}
|
|
258
|
+
warn(message, ...optionalParams) {
|
|
259
|
+
console.warn(this.formatMessage(message), ...optionalParams);
|
|
260
|
+
}
|
|
261
|
+
info(message, ...optionalParams) {
|
|
262
|
+
console.info(this.formatMessage(message), ...optionalParams);
|
|
263
|
+
}
|
|
264
|
+
debug(message, ...optionalParams) {
|
|
265
|
+
console.debug(this.formatMessage(message), ...optionalParams);
|
|
266
|
+
}
|
|
267
|
+
verbose(message, ...optionalParams) {
|
|
268
|
+
console.debug(this.formatMessage(message), ...optionalParams);
|
|
269
|
+
}
|
|
270
|
+
formatMessage(message) {
|
|
271
|
+
return `${this.prefix} ${message}`;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
247
275
|
// src/core/clients/RabbitMQClientAdapter.ts
|
|
248
276
|
var RabbitMQClientAdapter = class {
|
|
249
|
-
constructor(config) {
|
|
277
|
+
constructor(config, logger = new RunMQConsoleLogger()) {
|
|
250
278
|
this.config = config;
|
|
279
|
+
this.logger = logger;
|
|
251
280
|
this.isConnected = false;
|
|
252
281
|
this.acquiredChannels = [];
|
|
253
282
|
}
|
|
@@ -271,17 +300,17 @@ var RabbitMQClientAdapter = class {
|
|
|
271
300
|
connectionTimeout: 5e3
|
|
272
301
|
});
|
|
273
302
|
this.connection.on("error", (err) => {
|
|
274
|
-
|
|
303
|
+
this.logger.error("RabbitMQ connection error:", { error: err });
|
|
275
304
|
this.isConnected = false;
|
|
276
305
|
});
|
|
277
306
|
this.connection.on("connection", () => {
|
|
278
307
|
this.isConnected = true;
|
|
279
308
|
});
|
|
280
309
|
this.connection.on("connection.blocked", (reason) => {
|
|
281
|
-
|
|
310
|
+
this.logger.warn("RabbitMQ connection blocked:", { reason });
|
|
282
311
|
});
|
|
283
312
|
this.connection.on("connection.unblocked", () => {
|
|
284
|
-
|
|
313
|
+
this.logger.info("RabbitMQ connection unblocked");
|
|
285
314
|
});
|
|
286
315
|
await this.connection.onConnect(5e3, true);
|
|
287
316
|
this.isConnected = true;
|
|
@@ -368,7 +397,8 @@ var Constants = {
|
|
|
368
397
|
DEAD_LETTER_ROUTER_EXCHANGE_NAME: RUNMQ_PREFIX + "dead_letter_router",
|
|
369
398
|
RETRY_DELAY_QUEUE_PREFIX: RUNMQ_PREFIX + "retry_delay_",
|
|
370
399
|
DLQ_QUEUE_PREFIX: RUNMQ_PREFIX + "dlq_",
|
|
371
|
-
MESSAGE_TTL_OPERATOR_POLICY_PREFIX: RUNMQ_PREFIX + "message_ttl_operator_policy"
|
|
400
|
+
MESSAGE_TTL_OPERATOR_POLICY_PREFIX: RUNMQ_PREFIX + "message_ttl_operator_policy",
|
|
401
|
+
METADATA_STORE_PREFIX: RUNMQ_PREFIX + "metadata_"
|
|
372
402
|
};
|
|
373
403
|
var DEFAULTS = {
|
|
374
404
|
RECONNECT_DELAY: 5e3,
|
|
@@ -446,6 +476,27 @@ var RunMQFailedMessageRejecterProcessor = class {
|
|
|
446
476
|
}
|
|
447
477
|
};
|
|
448
478
|
|
|
479
|
+
// src/core/message/RunMQMessage.ts
|
|
480
|
+
var RunMQMessage = class {
|
|
481
|
+
static isValid(obj) {
|
|
482
|
+
if (typeof obj === "object" && obj !== null) {
|
|
483
|
+
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";
|
|
484
|
+
}
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
constructor(message, meta) {
|
|
488
|
+
this.message = message;
|
|
489
|
+
this.meta = meta;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
var RunMQMessageMeta = class {
|
|
493
|
+
constructor(id, publishedAt, correlationId) {
|
|
494
|
+
this.id = id;
|
|
495
|
+
this.correlationId = correlationId;
|
|
496
|
+
this.publishedAt = publishedAt;
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
449
500
|
// src/core/consumer/ConsumerCreatorUtils.ts
|
|
450
501
|
var ConsumerCreatorUtils = class {
|
|
451
502
|
static getDLQTopicName(topic) {
|
|
@@ -497,7 +548,28 @@ var RunMQRetriesCheckerProcessor = class {
|
|
|
497
548
|
);
|
|
498
549
|
}
|
|
499
550
|
moveToFinalDeadLetter(message) {
|
|
500
|
-
this.
|
|
551
|
+
const originalPayload = this.extractOriginalPayload(message);
|
|
552
|
+
const dlqMessage = new RabbitMQMessage(
|
|
553
|
+
originalPayload,
|
|
554
|
+
message.id,
|
|
555
|
+
message.correlationId,
|
|
556
|
+
message.channel,
|
|
557
|
+
message.amqpMessage,
|
|
558
|
+
message.headers
|
|
559
|
+
);
|
|
560
|
+
this.DLQPublisher.publish(ConsumerCreatorUtils.getDLQTopicName(this.config.name), dlqMessage);
|
|
561
|
+
}
|
|
562
|
+
extractOriginalPayload(message) {
|
|
563
|
+
if (typeof message.message === "string") {
|
|
564
|
+
try {
|
|
565
|
+
const parsed = JSON.parse(message.message);
|
|
566
|
+
if (RunMQMessage.isValid(parsed)) {
|
|
567
|
+
return parsed.message;
|
|
568
|
+
}
|
|
569
|
+
} catch (e) {
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return message.message;
|
|
501
573
|
}
|
|
502
574
|
acknowledgeMessage(message) {
|
|
503
575
|
try {
|
|
@@ -575,27 +647,6 @@ var RunMQExceptionLoggerProcessor = class {
|
|
|
575
647
|
}
|
|
576
648
|
};
|
|
577
649
|
|
|
578
|
-
// src/core/message/RunMQMessage.ts
|
|
579
|
-
var RunMQMessage = class {
|
|
580
|
-
static isValid(obj) {
|
|
581
|
-
if (typeof obj === "object" && obj !== null) {
|
|
582
|
-
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";
|
|
583
|
-
}
|
|
584
|
-
return false;
|
|
585
|
-
}
|
|
586
|
-
constructor(message, meta) {
|
|
587
|
-
this.message = message;
|
|
588
|
-
this.meta = meta;
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
var RunMQMessageMeta = class {
|
|
592
|
-
constructor(id, publishedAt, correlationId) {
|
|
593
|
-
this.id = id;
|
|
594
|
-
this.correlationId = correlationId;
|
|
595
|
-
this.publishedAt = publishedAt;
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
|
-
|
|
599
650
|
// src/core/serializers/deserializer/validation/AjvSchemaValidator.ts
|
|
600
651
|
var import_ajv = __toESM(require("ajv"), 1);
|
|
601
652
|
var AjvSchemaValidator = class {
|
|
@@ -870,6 +921,91 @@ var RabbitMQManagementClient = class {
|
|
|
870
921
|
return false;
|
|
871
922
|
}
|
|
872
923
|
}
|
|
924
|
+
/**
|
|
925
|
+
* Creates or updates a RabbitMQ parameter.
|
|
926
|
+
* Parameters are custom key-value stores that can hold any JSON data.
|
|
927
|
+
*
|
|
928
|
+
* @param name - The parameter name
|
|
929
|
+
* @param value - The parameter value (any JSON-serializable object)
|
|
930
|
+
*/
|
|
931
|
+
async setParameter(name, value) {
|
|
932
|
+
try {
|
|
933
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
934
|
+
const response = await fetch(url, {
|
|
935
|
+
method: "PUT",
|
|
936
|
+
headers: {
|
|
937
|
+
"Content-Type": "application/json",
|
|
938
|
+
"Authorization": this.getAuthHeader()
|
|
939
|
+
},
|
|
940
|
+
body: JSON.stringify({ value })
|
|
941
|
+
});
|
|
942
|
+
if (!response.ok) {
|
|
943
|
+
const error = await response.text();
|
|
944
|
+
this.logger.error(`Failed to set parameter ${name}: ${response.status} - ${error}`);
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
this.logger.info(`Successfully set parameter: ${name}`);
|
|
948
|
+
return true;
|
|
949
|
+
} catch (error) {
|
|
950
|
+
this.logger.error(`Error setting parameter: ${error}`);
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Gets a RabbitMQ parameter.
|
|
956
|
+
*
|
|
957
|
+
* @param name - The parameter name
|
|
958
|
+
*/
|
|
959
|
+
async getParameter(name) {
|
|
960
|
+
try {
|
|
961
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
962
|
+
const response = await fetch(url, {
|
|
963
|
+
method: "GET",
|
|
964
|
+
headers: {
|
|
965
|
+
"Authorization": this.getAuthHeader()
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
if (!response.ok) {
|
|
969
|
+
if (response.status === 404) {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
const error = await response.text();
|
|
973
|
+
this.logger.error(`Failed to get parameter ${name}: ${response.status} - ${error}`);
|
|
974
|
+
return null;
|
|
975
|
+
}
|
|
976
|
+
const data = await response.json();
|
|
977
|
+
return data.value;
|
|
978
|
+
} catch (error) {
|
|
979
|
+
this.logger.error(`Error getting parameter: ${error}`);
|
|
980
|
+
return null;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Deletes a RabbitMQ parameter.
|
|
985
|
+
*
|
|
986
|
+
* @param name - The parameter name
|
|
987
|
+
*/
|
|
988
|
+
async deleteParameter(name) {
|
|
989
|
+
try {
|
|
990
|
+
const url = `${this.config.url}/api/global-parameters/${encodeURIComponent(name)}`;
|
|
991
|
+
const response = await fetch(url, {
|
|
992
|
+
method: "DELETE",
|
|
993
|
+
headers: {
|
|
994
|
+
"Authorization": this.getAuthHeader()
|
|
995
|
+
}
|
|
996
|
+
});
|
|
997
|
+
if (!response.ok && response.status !== 404) {
|
|
998
|
+
const error = await response.text();
|
|
999
|
+
this.logger.error(`Failed to delete parameter ${name}: ${response.status} - ${error}`);
|
|
1000
|
+
return false;
|
|
1001
|
+
}
|
|
1002
|
+
this.logger.info(`Successfully deleted parameter: ${name}`);
|
|
1003
|
+
return true;
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
this.logger.error(`Error deleting parameter: ${error}`);
|
|
1006
|
+
return false;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
873
1009
|
};
|
|
874
1010
|
|
|
875
1011
|
// src/core/management/Policies/RabbitMQMessageTTLPolicy.ts
|
|
@@ -899,6 +1035,9 @@ var RunMQTTLPolicyManager = class {
|
|
|
899
1035
|
}
|
|
900
1036
|
}
|
|
901
1037
|
async initialize() {
|
|
1038
|
+
if (this.isManagementPluginEnabled) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
902
1041
|
if (!this.managementClient) {
|
|
903
1042
|
this.logger.warn("Management client not configured");
|
|
904
1043
|
return;
|
|
@@ -931,21 +1070,166 @@ var RunMQTTLPolicyManager = class {
|
|
|
931
1070
|
}
|
|
932
1071
|
};
|
|
933
1072
|
|
|
1073
|
+
// src/core/management/Policies/RunMQQueueMetadata.ts
|
|
1074
|
+
var METADATA_SCHEMA_VERSION = 0;
|
|
1075
|
+
|
|
1076
|
+
// src/core/management/Policies/RabbitMQMetadata.ts
|
|
1077
|
+
var RabbitMQMetadata = class {
|
|
1078
|
+
/**
|
|
1079
|
+
* Creates metadata for a queue.
|
|
1080
|
+
* @param maxRetries - Maximum retry attempts configured for the queue
|
|
1081
|
+
* @param existingMetadata - Optional existing metadata to preserve createdAt
|
|
1082
|
+
* @returns RunMQQueueMetadata object
|
|
1083
|
+
*/
|
|
1084
|
+
static createMetadataFor(maxRetries, existingMetadata) {
|
|
1085
|
+
var _a2;
|
|
1086
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1087
|
+
return __spreadValues({
|
|
1088
|
+
version: METADATA_SCHEMA_VERSION,
|
|
1089
|
+
maxRetries,
|
|
1090
|
+
createdAt: (_a2 = existingMetadata == null ? void 0 : existingMetadata.createdAt) != null ? _a2 : now
|
|
1091
|
+
}, existingMetadata ? { updatedAt: now } : {});
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Gets the parameter name for a given queue.
|
|
1095
|
+
*/
|
|
1096
|
+
static getParameterName(queueName) {
|
|
1097
|
+
return Constants.METADATA_STORE_PREFIX + queueName;
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
// src/core/management/Policies/RunMQMetadataManager.ts
|
|
1102
|
+
var RunMQMetadataManager = class {
|
|
1103
|
+
constructor(logger, managementConfig) {
|
|
1104
|
+
this.logger = logger;
|
|
1105
|
+
this.managementConfig = managementConfig;
|
|
1106
|
+
this.managementClient = null;
|
|
1107
|
+
this.isManagementPluginEnabled = false;
|
|
1108
|
+
if (this.managementConfig) {
|
|
1109
|
+
this.managementClient = new RabbitMQManagementClient(this.managementConfig, this.logger);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Initialize the manager by checking if management plugin is available.
|
|
1114
|
+
*/
|
|
1115
|
+
async initialize() {
|
|
1116
|
+
if (this.isManagementPluginEnabled) {
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
if (!this.managementClient) {
|
|
1120
|
+
this.logger.warn("Management client not configured - metadata storage disabled");
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
this.isManagementPluginEnabled = await this.managementClient.checkManagementPluginEnabled();
|
|
1124
|
+
if (!this.isManagementPluginEnabled) {
|
|
1125
|
+
this.logger.warn("RabbitMQ management plugin is not enabled - metadata storage disabled");
|
|
1126
|
+
} else {
|
|
1127
|
+
this.logger.info("RunMQ metadata storage initialized");
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Store or update metadata for a queue.
|
|
1132
|
+
* If metadata already exists, preserves createdAt and sets updatedAt.
|
|
1133
|
+
*
|
|
1134
|
+
* @param queueName - The name of the queue
|
|
1135
|
+
* @param maxRetries - Maximum retry attempts
|
|
1136
|
+
* @returns true if metadata was stored successfully, false otherwise
|
|
1137
|
+
*/
|
|
1138
|
+
async apply(queueName, maxRetries) {
|
|
1139
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1140
|
+
this.logger.warn(`Cannot store metadata for queue '${queueName}' - management plugin not available`);
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
try {
|
|
1144
|
+
const existingMetadata = await this.getMetadata(queueName);
|
|
1145
|
+
const metadata = RabbitMQMetadata.createMetadataFor(
|
|
1146
|
+
maxRetries,
|
|
1147
|
+
existingMetadata != null ? existingMetadata : void 0
|
|
1148
|
+
);
|
|
1149
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1150
|
+
const success = await this.managementClient.setParameter(
|
|
1151
|
+
paramName,
|
|
1152
|
+
metadata
|
|
1153
|
+
);
|
|
1154
|
+
if (success) {
|
|
1155
|
+
const action = existingMetadata ? "Updated" : "Created";
|
|
1156
|
+
this.logger.info(`${action} metadata for queue: ${queueName}`);
|
|
1157
|
+
return true;
|
|
1158
|
+
}
|
|
1159
|
+
this.logger.error(`Failed to store metadata for queue: ${queueName}`);
|
|
1160
|
+
return false;
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
this.logger.error(`Error storing metadata for queue ${queueName}: ${error}`);
|
|
1163
|
+
return false;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Get metadata for a queue.
|
|
1168
|
+
*
|
|
1169
|
+
* @param queueName - The name of the queue
|
|
1170
|
+
* @returns The queue metadata or null if not found
|
|
1171
|
+
*/
|
|
1172
|
+
async getMetadata(queueName) {
|
|
1173
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1174
|
+
return null;
|
|
1175
|
+
}
|
|
1176
|
+
try {
|
|
1177
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1178
|
+
return await this.managementClient.getParameter(
|
|
1179
|
+
paramName
|
|
1180
|
+
);
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
this.logger.warn(`Failed to get metadata for queue ${queueName}: ${error}`);
|
|
1183
|
+
return null;
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Delete metadata for a queue.
|
|
1188
|
+
*
|
|
1189
|
+
* @param queueName - The name of the queue
|
|
1190
|
+
*/
|
|
1191
|
+
async cleanup(queueName) {
|
|
1192
|
+
if (!this.isManagementPluginEnabled || !this.managementClient) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
const paramName = RabbitMQMetadata.getParameterName(queueName);
|
|
1196
|
+
await this.managementClient.deleteParameter(paramName);
|
|
1197
|
+
this.logger.info(`Deleted metadata for queue: ${queueName}`);
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Check if management plugin is enabled and metadata storage is available.
|
|
1201
|
+
*/
|
|
1202
|
+
isEnabled() {
|
|
1203
|
+
return this.isManagementPluginEnabled;
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
|
|
934
1207
|
// src/core/consumer/RunMQConsumerCreator.ts
|
|
935
1208
|
var RunMQConsumerCreator = class {
|
|
936
1209
|
constructor(client, logger, managementConfig) {
|
|
937
1210
|
this.client = client;
|
|
938
1211
|
this.logger = logger;
|
|
939
1212
|
this.ttlPolicyManager = new RunMQTTLPolicyManager(logger, managementConfig);
|
|
1213
|
+
this.metadataManager = new RunMQMetadataManager(logger, managementConfig);
|
|
940
1214
|
}
|
|
941
1215
|
async createConsumer(consumerConfiguration) {
|
|
942
1216
|
await this.ttlPolicyManager.initialize();
|
|
1217
|
+
await this.metadataManager.initialize();
|
|
943
1218
|
await this.assertQueues(consumerConfiguration);
|
|
944
1219
|
await this.bindQueues(consumerConfiguration);
|
|
1220
|
+
await this.storeMetadata(consumerConfiguration);
|
|
945
1221
|
for (let i = 0; i < consumerConfiguration.processorConfig.consumersCount; i++) {
|
|
946
1222
|
await this.runProcessor(consumerConfiguration);
|
|
947
1223
|
}
|
|
948
1224
|
}
|
|
1225
|
+
async storeMetadata(consumerConfiguration) {
|
|
1226
|
+
var _a2;
|
|
1227
|
+
const maxRetries = (_a2 = consumerConfiguration.processorConfig.attempts) != null ? _a2 : DEFAULTS.PROCESSING_ATTEMPTS;
|
|
1228
|
+
await this.metadataManager.apply(
|
|
1229
|
+
consumerConfiguration.processorConfig.name,
|
|
1230
|
+
maxRetries
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
949
1233
|
async runProcessor(consumerConfiguration) {
|
|
950
1234
|
const consumerChannel = await this.getProcessorChannel();
|
|
951
1235
|
const DLQPublisher = new RunMQPublisherCreator(this.logger).createPublisher(Constants.DEAD_LETTER_ROUTER_EXCHANGE_NAME);
|
|
@@ -1062,34 +1346,6 @@ var ConsumerConfiguration = class {
|
|
|
1062
1346
|
}
|
|
1063
1347
|
};
|
|
1064
1348
|
|
|
1065
|
-
// src/core/logging/RunMQConsoleLogger.ts
|
|
1066
|
-
var RunMQConsoleLogger = class {
|
|
1067
|
-
constructor() {
|
|
1068
|
-
this.prefix = "[RunMQ] - ";
|
|
1069
|
-
}
|
|
1070
|
-
log(message) {
|
|
1071
|
-
console.log(this.formatMessage(message));
|
|
1072
|
-
}
|
|
1073
|
-
error(message, ...optionalParams) {
|
|
1074
|
-
console.error(this.formatMessage(message), ...optionalParams);
|
|
1075
|
-
}
|
|
1076
|
-
warn(message, ...optionalParams) {
|
|
1077
|
-
console.warn(this.formatMessage(message), ...optionalParams);
|
|
1078
|
-
}
|
|
1079
|
-
info(message, ...optionalParams) {
|
|
1080
|
-
console.info(this.formatMessage(message), ...optionalParams);
|
|
1081
|
-
}
|
|
1082
|
-
debug(message, ...optionalParams) {
|
|
1083
|
-
console.debug(this.formatMessage(message), ...optionalParams);
|
|
1084
|
-
}
|
|
1085
|
-
verbose(message, ...optionalParams) {
|
|
1086
|
-
console.debug(this.formatMessage(message), ...optionalParams);
|
|
1087
|
-
}
|
|
1088
|
-
formatMessage(message) {
|
|
1089
|
-
return `${this.prefix} ${message}`;
|
|
1090
|
-
}
|
|
1091
|
-
};
|
|
1092
|
-
|
|
1093
1349
|
// src/core/message/RabbitMQMessageProperties.ts
|
|
1094
1350
|
var RabbitMQMessageProperties = class {
|
|
1095
1351
|
constructor(id, correlationId) {
|
|
@@ -1108,7 +1364,8 @@ var RunMQ = class _RunMQ {
|
|
|
1108
1364
|
reconnectDelay: (_a2 = config.reconnectDelay) != null ? _a2 : DEFAULTS.RECONNECT_DELAY,
|
|
1109
1365
|
maxReconnectAttempts: (_b = config.maxReconnectAttempts) != null ? _b : DEFAULTS.MAX_RECONNECT_ATTEMPTS
|
|
1110
1366
|
});
|
|
1111
|
-
this.client = new RabbitMQClientAdapter(this.config);
|
|
1367
|
+
this.client = new RabbitMQClientAdapter(this.config, this.logger);
|
|
1368
|
+
this.consumer = new RunMQConsumerCreator(this.client, this.logger, this.config.management);
|
|
1112
1369
|
}
|
|
1113
1370
|
/**
|
|
1114
1371
|
* Starts the RunMQ instance by establishing a connection to RabbitMQ and initializing necessary components.
|
|
@@ -1129,8 +1386,7 @@ var RunMQ = class _RunMQ {
|
|
|
1129
1386
|
* @param processor The function that will process the incoming messages
|
|
1130
1387
|
*/
|
|
1131
1388
|
async process(topic, config, processor) {
|
|
1132
|
-
|
|
1133
|
-
await consumer.createConsumer(new ConsumerConfiguration(topic, config, processor));
|
|
1389
|
+
await this.consumer.createConsumer(new ConsumerConfiguration(topic, config, processor));
|
|
1134
1390
|
}
|
|
1135
1391
|
/**
|
|
1136
1392
|
* Publishes a message to the specified topic with an optional correlation ID
|
|
@@ -1189,7 +1445,6 @@ var RunMQ = class _RunMQ {
|
|
|
1189
1445
|
return;
|
|
1190
1446
|
} catch (error) {
|
|
1191
1447
|
this.retryAttempts++;
|
|
1192
|
-
console.log(this.logger);
|
|
1193
1448
|
this.logger.error(`Connection attempt ${this.retryAttempts}/${maxAttempts} failed:`, error);
|
|
1194
1449
|
if (this.retryAttempts >= maxAttempts) {
|
|
1195
1450
|
throw new RunMQException(
|