@platform-x/hep-message-broker-client 1.0.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.
Files changed (42) hide show
  1. package/README.md +1 -0
  2. package/dist/src/Util/commonUtil.d.ts +16 -0
  3. package/dist/src/Util/commonUtil.js +39 -0
  4. package/dist/src/Util/logger.d.ts +68 -0
  5. package/dist/src/Util/logger.js +195 -0
  6. package/dist/src/Util/requestTracer.d.ts +7 -0
  7. package/dist/src/Util/requestTracer.js +34 -0
  8. package/dist/src/config/ConfigManager.d.ts +9 -0
  9. package/dist/src/config/ConfigManager.js +67 -0
  10. package/dist/src/config/index.d.ts +29 -0
  11. package/dist/src/config/index.js +38 -0
  12. package/dist/src/index.d.ts +2 -0
  13. package/dist/src/index.js +6 -0
  14. package/dist/src/messageBroker/BaseRabbitMQClient.d.ts +16 -0
  15. package/dist/src/messageBroker/BaseRabbitMQClient.js +29 -0
  16. package/dist/src/messageBroker/ConnectionManager.d.ts +60 -0
  17. package/dist/src/messageBroker/ConnectionManager.js +227 -0
  18. package/dist/src/messageBroker/MessageBrokerClient.d.ts +34 -0
  19. package/dist/src/messageBroker/MessageBrokerClient.js +102 -0
  20. package/dist/src/messageBroker/MessageConsumer.d.ts +26 -0
  21. package/dist/src/messageBroker/MessageConsumer.js +102 -0
  22. package/dist/src/messageBroker/MessageProducer.d.ts +29 -0
  23. package/dist/src/messageBroker/MessageProducer.js +130 -0
  24. package/dist/src/messageBroker/RabbitMQClient.d.ts +12 -0
  25. package/dist/src/messageBroker/RabbitMQClient.js +67 -0
  26. package/dist/src/messageBroker/RetryManager.d.ts +23 -0
  27. package/dist/src/messageBroker/RetryManager.js +72 -0
  28. package/dist/src/messageBroker/interface/ConnectionWrapper.d.ts +6 -0
  29. package/dist/src/messageBroker/interface/ConnectionWrapper.js +3 -0
  30. package/dist/src/messageBroker/interface/IMessageBrokerClient.d.ts +7 -0
  31. package/dist/src/messageBroker/interface/IMessageBrokerClient.js +3 -0
  32. package/dist/src/messageBroker/rabbitmq/MessageBrokerClient.d.ts +114 -0
  33. package/dist/src/messageBroker/rabbitmq/MessageBrokerClient.js +706 -0
  34. package/dist/src/messageBroker/types/ActionType.d.ts +1 -0
  35. package/dist/src/messageBroker/types/ActionType.js +3 -0
  36. package/dist/src/messageBroker/types/PublishMessageInputType.d.ts +7 -0
  37. package/dist/src/messageBroker/types/PublishMessageInputType.js +3 -0
  38. package/dist/src/models/MessageModel.d.ts +5 -0
  39. package/dist/src/models/MessageModel.js +15 -0
  40. package/dist/src/models/NotificationMessageModel.d.ts +0 -0
  41. package/dist/src/models/NotificationMessageModel.js +2 -0
  42. package/package.json +40 -0
@@ -0,0 +1,706 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ var _a;
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.MessageBrokerClient = void 0;
50
+ // Import the amqplib library for RabbitMQ
51
+ const amqp = __importStar(require("amqplib"));
52
+ const config_1 = __importDefault(require("../../config"));
53
+ const logger_1 = require("../../Util/logger");
54
+ const ConfigManager_1 = __importDefault(require("../../config/ConfigManager"));
55
+ // Remove lodash delay import
56
+ let configManager = ConfigManager_1.default.getInstance();
57
+ // Declare variables for the connection and channel
58
+ let connection;
59
+ let channel;
60
+ // Declare variable for check connection
61
+ let isConnectionOpen = false;
62
+ let configData = {};
63
+ const RABBITMQ = config_1.default === null || config_1.default === void 0 ? void 0 : config_1.default.RABBITMQ;
64
+ let maxRetries = RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.MAX_RETRIES;
65
+ let retry_delay = (_a = RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.TTL) === null || _a === void 0 ? void 0 : _a.split("|");
66
+ // let dlx_exchange:string = RABBITMQ.DLX_EXCHANGE;
67
+ let dlx_queue = RABBITMQ.DLX_QUEUE;
68
+ // let retry_exchange:string = RABBITMQ.RETRY_EXCHANGE;
69
+ // let retry_queue:string = RABBITMQ.RETRY_QUEUE;
70
+ let connectionRetry = 1;
71
+ let retryCountHeader = 'x-retry-count';
72
+ class MessageBrokerClient {
73
+ // private readonly correlationId: string;
74
+ // constructor() {
75
+ // this.correlationId = generateCorrelationId();
76
+ // }
77
+ /**
78
+ * Function to check the status of the connection
79
+ * @returns boolean
80
+ */
81
+ isConnected() {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ return isConnectionOpen;
84
+ });
85
+ }
86
+ ;
87
+ /**
88
+ * Function to initialize the connection, channel and setup the queues and exchanges
89
+ * @param reqData
90
+ * @returns
91
+ */
92
+ initialize() {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ logger_1.Logger.info('Reached to initialize', 'initialize');
95
+ configData = configManager.getConfig();
96
+ // dlx_exchange = configData?.dlx_exchange;
97
+ dlx_queue = configData === null || configData === void 0 ? void 0 : configData.dlx_queue;
98
+ // retry_exchange = configData?.retry_exchange;
99
+ // retry_queue = configData?.retry_queue;
100
+ let retries = 0;
101
+ // Retrie times connection
102
+ while (retries < maxRetries) {
103
+ try {
104
+ if (RABBITMQ.CONNECTION_ERROR === 'true' || RABBITMQ.CONNECTION_ERROR === true) {
105
+ throw new Error("Error in connection");
106
+ }
107
+ yield this.createConnection();
108
+ return { connection: connection, channel: channel };
109
+ }
110
+ catch (err) {
111
+ retries++;
112
+ logger_1.Logger.error('initialize:Failed to connect to RabbitMQ', `Attempt ${retries} of ${maxRetries}.`);
113
+ if (retries >= maxRetries) {
114
+ logger_1.Logger.error('Max retries reached, cannot connect to RabbitMQ.', 'initialize');
115
+ return { connection, channel };
116
+ }
117
+ // Wait before retrying (e.g., 10 seconds)
118
+ yield new Promise(resolve => setTimeout(resolve, 10000));
119
+ }
120
+ }
121
+ });
122
+ }
123
+ ;
124
+ /**
125
+ * Function to publish a message with retry
126
+ * @param request
127
+ * @param classInstance
128
+ * @param messagePublisherErrorHandler
129
+ * @returns
130
+ */
131
+ publishMessage(request
132
+ // , classInstance:any, messagePublisherErrorHandler:string
133
+ ) {
134
+ return __awaiter(this, void 0, void 0, function* () {
135
+ logger_1.Logger.info('Reached:publishMessage', 'publishMessage');
136
+ // Logger.debug('Reached:publishMessageToExchange', 'publishMessageToExchange',{classInstance, messagePublisherErrorHandler});
137
+ try {
138
+ if (isConnectionOpen) {
139
+ logger_1.Logger.info('Check connection open or not', 'publishMessage');
140
+ const queueName = request.queueName;
141
+ const data = request.message;
142
+ const messageBuffer = Buffer.from(JSON.stringify(data === null || data === void 0 ? void 0 : data.message));
143
+ // let attempt: number = 0;
144
+ // let retries: number = typeof data.message === 'object' && data.message !== null ? (data.message as { retries: number }).retries ?? 0 : 0;
145
+ // while (attempt < maxRetries ) {
146
+ logger_1.Logger.info('Max retries check', 'publishMessage');
147
+ const isSent = yield new Promise((resolve, reject) => {
148
+ let sent = channel.sendToQueue(queueName, Buffer.from(messageBuffer), {
149
+ persistent: true, // Ensures the message is persisted
150
+ // correlationId: this.correlationId,
151
+ });
152
+ if (sent) {
153
+ logger_1.Logger.debug(`Message sent successfully`, 'publishMessage', { data, queueName });
154
+ resolve(true);
155
+ }
156
+ else {
157
+ logger_1.Logger.error(`Failed to publish message.`, 'publishMessage', { message: messageBuffer.toString() });
158
+ reject(false);
159
+ }
160
+ });
161
+ if ((isSent) && (RABBITMQ.PUBLISHER_ERROR !== 'true' && RABBITMQ.PUBLISHER_ERROR !== true)) {
162
+ return isSent;
163
+ }
164
+ // else{
165
+ // let queueName = (request as PublishMessageInputType)?.queueName
166
+ // if (attempt >= maxRetries) {
167
+ // Logger.error('Max retries reached. Failed to publish message.', 'publishMessage', request);
168
+ // // Optionally: Log or persist the failed message to a DB, file, or other storage for manual intervention
169
+ // this.sendMessageToDeadLatter(attempt, data, queueName);
170
+ // this.messagePublisherErrorHandler(request); // we need to comment this line
171
+ // if (typeof classInstance[messagePublisherErrorHandler] === 'function') {
172
+ // classInstance[messagePublisherErrorHandler](data); // Dynamically call the method
173
+ // } else {
174
+ // Logger.info(`Method ${messagePublisherErrorHandler} not found in classInstance.`, 'publishMessage');
175
+ // }
176
+ // return false;
177
+ // }else{
178
+ // await this.publishMessageRetryQueue(request, attempt);
179
+ // attempt++;
180
+ // }
181
+ // }
182
+ // }
183
+ }
184
+ }
185
+ catch (error) {
186
+ logger_1.Logger.error(`Error sending message: ${error}`, 'sendMessage');
187
+ throw new Error("Failed to publish message to queue");
188
+ }
189
+ });
190
+ }
191
+ /**
192
+ * Function to publish a message with retry
193
+ * @param request
194
+ * @param classInstance
195
+ * @param messagePublisherErrorHandler
196
+ * @returns
197
+ */
198
+ publishMessageToExchange(request) {
199
+ return __awaiter(this, void 0, void 0, function* () {
200
+ var _a;
201
+ logger_1.Logger.info('Reached:publishMessageToExchange', 'publishMessageToExchange');
202
+ // Publish the message
203
+ // Logger.debug('Reached:publishMessageToExchange', 'publishMessageToExchange',{classInstance, messagePublisherErrorHandler});
204
+ try {
205
+ if (isConnectionOpen) {
206
+ // let attempt: number = 0;
207
+ const exchangeName = (_a = request === null || request === void 0 ? void 0 : request.exchangeName) !== null && _a !== void 0 ? _a : '';
208
+ const queueName = request.queueName;
209
+ const data = request === null || request === void 0 ? void 0 : request.message;
210
+ // const options:object | null = request?.options; // Optional parameter for retry count if you wnats to override the default retry count
211
+ const messageBuffer = Buffer.from(JSON.stringify(data.message));
212
+ // let retries: number = typeof data.message === 'object' && data.message !== null ? (data.message as { retries: number }).retries ?? 0 : 0;
213
+ // while (attempt < maxRetries) {
214
+ const isSent = yield new Promise((resolve, reject) => {
215
+ const sent = channel.publish(exchangeName, queueName, messageBuffer, {
216
+ persistent: true, // Ensures the message is persisted
217
+ // correlationId: this.correlationId,
218
+ });
219
+ if (sent) {
220
+ logger_1.Logger.debug(`Message sent successfully`, 'publishMessageToExchange', { data, queueName });
221
+ resolve(true);
222
+ }
223
+ else {
224
+ logger_1.Logger.error(`Failed to publish message to exchange.`, 'publishMessageToExchange', { message: messageBuffer.toString() });
225
+ reject(false);
226
+ }
227
+ });
228
+ if ((isSent) && (RABBITMQ.PUBLISHER_ERROR !== 'true' && RABBITMQ.PUBLISHER_ERROR !== true)) {
229
+ return isSent;
230
+ }
231
+ // else{
232
+ // let queueName = (request as PublishMessageInputType)?.queueName
233
+ // if (attempt >= maxRetries) {
234
+ // Logger.error('Max retries reached. Failed to publish message.', 'publishMessageToExchange', request);
235
+ // // Optionally: Log or persist the failed message to a DB, file, or other storage for manual intervention
236
+ // this.sendMessageToDeadLatter(attempt, data, queueName);
237
+ // this.messagePublisherErrorHandler(request); // we need to comment this line
238
+ // if (typeof classInstance[messagePublisherErrorHandler] === 'function') {
239
+ // classInstance[messagePublisherErrorHandler](data); // Dynamically call the method
240
+ // } else {
241
+ // Logger.info(`Method ${messagePublisherErrorHandler} not found in classInstance.`, 'publishMessageToExchange');
242
+ // }
243
+ // return false;
244
+ // }else{
245
+ // await this.publishMessageRetryQueue(request, (attempt+1));
246
+ // attempt++;
247
+ // }
248
+ // }
249
+ // }
250
+ }
251
+ }
252
+ catch (error) {
253
+ logger_1.Logger.error(`Error sending message: ${error}`, 'sendMessage');
254
+ throw new Error("Failed to publish message to exchange");
255
+ }
256
+ });
257
+ }
258
+ ;
259
+ /**
260
+ * Funciton to message handler
261
+ */
262
+ // TO Do rename function name messagePublisherErrorHandler
263
+ messagePublisherErrorHandler(request) {
264
+ return __awaiter(this, void 0, void 0, function* () {
265
+ logger_1.Logger.info(`${JSON.stringify(request)}`, 'messagePublisherErrorHandler');
266
+ return Promise.resolve(true);
267
+ });
268
+ }
269
+ /**
270
+ * Funvction for initialize consumer queue
271
+ * @param consumerQueues
272
+ */
273
+ initializeConsumers(classInstance, consumerHandler, consumerErrorHandler) {
274
+ return __awaiter(this, void 0, void 0, function* () {
275
+ try {
276
+ logger_1.Logger.info('Reached in initialize consumer', `initializeConsumers`);
277
+ let consume_queues = configData === null || configData === void 0 ? void 0 : configData.consume_queues;
278
+ // Consume messages from all queues
279
+ for (let queueName in configData === null || configData === void 0 ? void 0 : configData.consume_queues) {
280
+ if (Object.prototype.hasOwnProperty.call(consume_queues, queueName)) {
281
+ // Call function Consume messages with retry
282
+ yield this.consumeMessage(queueName, classInstance, consumerHandler, consumerErrorHandler);
283
+ }
284
+ }
285
+ }
286
+ catch (error) {
287
+ logger_1.Logger.error('Error initializing consumers:', 'initializeConsumers', error.message);
288
+ throw new Error(error.message);
289
+ }
290
+ });
291
+ }
292
+ /**
293
+ * Function for perform action with retry
294
+ * @param actionHandler
295
+ * @param context
296
+ * @param failActionHandler
297
+ * @returns
298
+ */
299
+ performActionWithRetry(actionHandler, failActionHandler, context) {
300
+ return __awaiter(this, void 0, void 0, function* () {
301
+ logger_1.Logger.info("Reached: in perform action with retry ", "performActionWithRetry");
302
+ let attempt = 0;
303
+ while (attempt < maxRetries) {
304
+ try {
305
+ actionHandler(context);
306
+ return true;
307
+ }
308
+ catch (error) {
309
+ attempt++;
310
+ logger_1.Logger.error(`Failed to publish message. Attempt ${attempt} of ${maxRetries}. Error:`, 'performActionWithRetry', { message: error.message });
311
+ let queueName = context === null || context === void 0 ? void 0 : context.queueName;
312
+ const data = context === null || context === void 0 ? void 0 : context.message;
313
+ if (attempt >= maxRetries) {
314
+ logger_1.Logger.error('Max retries reached. Failed to publish message.', 'performActionWithRetry');
315
+ // Optionally: Log or persist the failed message to a DB, file, or other storage for manual intervention
316
+ this.sendMessageToDeadLatter(attempt, data);
317
+ failActionHandler(context);
318
+ return false;
319
+ }
320
+ // Wait before retrying (Exponential Backoff)
321
+ let retryDelay;
322
+ retryDelay = Number(retry_delay[attempt - 1]);
323
+ let count = retry_delay.length - 1 === attempt ? retry_delay.length - 1 : retry_delay[attempt - 1];
324
+ retryDelay = Number(count);
325
+ this.sendMessageToRetryQueue(attempt, data, retryDelay, queueName);
326
+ logger_1.Logger.info(`Retrying in ${retryDelay / 1000} seconds...`, 'performActionWithRetry');
327
+ yield new Promise((resolve) => setTimeout(resolve, retryDelay));
328
+ }
329
+ }
330
+ return false;
331
+ });
332
+ }
333
+ /**
334
+ * Function to consume message with retry
335
+ * @param queueName
336
+ */
337
+ consumeMessage(queueName, classInstance, consumerHandler, consumerErrorHandler) {
338
+ return __awaiter(this, void 0, void 0, function* () {
339
+ logger_1.Logger.info("Reached: Consuming messages from the queue", 'consumeMessage');
340
+ let attempt = 0;
341
+ if (isConnectionOpen) {
342
+ return yield channel.consume(queueName, (message) => __awaiter(this, void 0, void 0, function* () {
343
+ var _a;
344
+ if (message) {
345
+ let msgData = JSON.parse(message.content.toString());
346
+ const headers = message.properties.headers || {};
347
+ attempt = headers[retryCountHeader] || 0;
348
+ const data = { body: (_a = msgData === null || msgData === void 0 ? void 0 : msgData.result) === null || _a === void 0 ? void 0 : _a.data, queue_name: queueName, language: msgData === null || msgData === void 0 ? void 0 : msgData.language, correlationId: msgData === null || msgData === void 0 ? void 0 : msgData.correlationId, retries: msgData === null || msgData === void 0 ? void 0 : msgData.retries, item_id: msgData === null || msgData === void 0 ? void 0 : msgData.item_id, metadatakey: msgData === null || msgData === void 0 ? void 0 : msgData.metadatakey };
349
+ try {
350
+ let success = false;
351
+ if (RABBITMQ.CONSUMER_ERROR !== 'true' && RABBITMQ.CONSUMER_ERROR !== true) {
352
+ logger_1.Logger.info("Consumer handler call for process the request", 'consumeMessage');
353
+ // success = await this.consumerHandler({ queueName, message: msgData });
354
+ if (typeof classInstance[consumerHandler] === 'function') {
355
+ success = yield classInstance[consumerHandler]({ queueName, message: msgData }); // Dynamically call the method
356
+ }
357
+ else {
358
+ logger_1.Logger.info(`Method ${consumerHandler} not found in classInstance.`, 'consumerMessage');
359
+ }
360
+ }
361
+ if (!success) {
362
+ const retryCount = message.properties.headers['x-retry-count'] || 0;
363
+ // while (retryCount < maxRetries) {
364
+ attempt = retryCount ? retryCount : attempt;
365
+ if (retryCount >= maxRetries) {
366
+ logger_1.Logger.error('Max retries reached. Failed to publish message.', 'consumeMessage');
367
+ // Optionally: Log or persist the failed message to a DB, file, or other storage for manual intervention
368
+ this.sendMessageToDeadLatter(attempt, data);
369
+ // this.consumerErrorHandler(data);
370
+ if (typeof classInstance[consumerErrorHandler] === 'function') {
371
+ classInstance[consumerErrorHandler](data); // Dynamically call the method
372
+ }
373
+ else {
374
+ logger_1.Logger.info(`Method ${consumerErrorHandler} not found in classInstance.`, 'consumerMessage');
375
+ }
376
+ channel.nack(message, false, false); // Move message to DLQ after failure
377
+ return false;
378
+ }
379
+ attempt++;
380
+ if ((data === null || data === void 0 ? void 0 : data.retries) >= 0) {
381
+ data.retries = attempt;
382
+ }
383
+ // Wait before retrying (Exponential Backoff)
384
+ let retryDelay;
385
+ let count = retry_delay.length === attempt ? retry_delay[retry_delay.length - 1] : retry_delay[attempt - 1];
386
+ retryDelay = Number(count);
387
+ yield this.sendMessageToRetryQueue(attempt, data, retryDelay, queueName);
388
+ logger_1.Logger.info(`Retrying in ${retryDelay / 1000} seconds...`, 'consumeMessage');
389
+ yield new Promise((resolve) => setTimeout(resolve, retryDelay));
390
+ }
391
+ else {
392
+ logger_1.Logger.info(`Acknowledge the successful processing`, 'consumeMessage');
393
+ }
394
+ // Acknowledge the successful processing
395
+ channel.ack(message);
396
+ }
397
+ catch (error) {
398
+ let errorMessage = error.message;
399
+ logger_1.Logger.error(`Error processing message`, 'consumeMessage', { message: errorMessage });
400
+ this.sendMessageToDeadLatter(attempt, data);
401
+ // this.consumerErrorHandler(data);
402
+ if (typeof classInstance[consumerErrorHandler] === 'function') {
403
+ classInstance[consumerErrorHandler](data); // Dynamically call the method
404
+ }
405
+ else {
406
+ logger_1.Logger.info(`Method ${consumerErrorHandler} not found in classInstance.`, 'consumerMessage');
407
+ }
408
+ channel.nack(message, false, false); // Move message to DLQ after failure
409
+ }
410
+ }
411
+ }));
412
+ }
413
+ });
414
+ }
415
+ ;
416
+ // /**
417
+ // * Function for consumer massage handler
418
+ // * @param request
419
+ // * @returns
420
+ // */
421
+ // public async consumerHandler(request: PublishMessageInputType): Promise<boolean> {
422
+ // Logger.info(`${JSON.stringify(request)}`, 'consumerHandler');
423
+ // return true;
424
+ // }
425
+ // /**
426
+ // * Function to consumer message error handler
427
+ // * @param request
428
+ // * @returns
429
+ // */
430
+ // public async consumerErrorHandler(request:any):Promise<boolean> {
431
+ // Logger.info(`${JSON.stringify(request)}`, 'consumerErrorHandler');
432
+ // return true;
433
+ // }
434
+ /**
435
+ * Function to send message to dead later queue
436
+ * @param attempt
437
+ * @param data
438
+ * @param queueName
439
+ * @retruns
440
+ */
441
+ sendMessageToDeadLatter(attempt, data) {
442
+ return __awaiter(this, void 0, void 0, function* () {
443
+ logger_1.Logger.info("Reached: send message on dead later queue", 'sendMessageToDeadLater');
444
+ try {
445
+ if (isConnectionOpen) {
446
+ return channel.sendToQueue(dlx_queue, Buffer.from(JSON.stringify(data)), {
447
+ persistent: true,
448
+ headers: {
449
+ 'x-retry-count': attempt - 1
450
+ },
451
+ });
452
+ }
453
+ }
454
+ catch (error) {
455
+ logger_1.Logger.error("Error in send message on dead later queue", 'sendMessageToDeadLater', { message: error.message });
456
+ throw error;
457
+ }
458
+ });
459
+ }
460
+ /***
461
+ * Function to send message to retry queue
462
+ * @param attempt
463
+ * @param data
464
+ * @param retryDelay
465
+ * @param queueName
466
+ * @returns
467
+ */
468
+ sendMessageToRetryQueue(attempt, data, retryDelay, queueName) {
469
+ return __awaiter(this, void 0, void 0, function* () {
470
+ logger_1.Logger.info("Reached: send message on retry queue", 'sendMessageToRetryQueue');
471
+ try {
472
+ if (isConnectionOpen) {
473
+ const isSent = yield new Promise((resolve, reject) => {
474
+ const messageBuffer = Buffer.from(JSON.stringify(data));
475
+ let sent = channel.sendToQueue(queueName, messageBuffer, {
476
+ headers: {
477
+ 'x-retry-count': attempt + 1,
478
+ 'x-message-ttl': retryDelay,
479
+ }
480
+ });
481
+ if (sent) {
482
+ logger_1.Logger.debug(`Message sent successfully`, 'publishMessage', { data, queueName });
483
+ resolve(true);
484
+ }
485
+ else {
486
+ logger_1.Logger.error(`Failed to publish message.`, 'publishMessage', { message: data.toString() });
487
+ reject(false);
488
+ }
489
+ });
490
+ return isSent;
491
+ }
492
+ }
493
+ catch (error) {
494
+ logger_1.Logger.error("Error in send message on retry queue", 'sendMessageToRetryQueue', { message: error.message });
495
+ throw error;
496
+ }
497
+ });
498
+ }
499
+ /**
500
+ * Function to find the queue, exchange and add binding
501
+ * @param queueName
502
+ * @param exchangeName
503
+ * @returns
504
+ */
505
+ findQueueAndExchange(queueName, exchangeName) {
506
+ return __awaiter(this, void 0, void 0, function* () {
507
+ var _a;
508
+ logger_1.Logger.info('Reached to findQueueAndExchange', 'findQueueAndExchange');
509
+ try {
510
+ let exchanges = configData === null || configData === void 0 ? void 0 : configData.exchanges;
511
+ let queues = configData.queues;
512
+ let bindings = configData.bindings;
513
+ // Declare the queues with dlx
514
+ for (let data of queues) {
515
+ if ((data === null || data === void 0 ? void 0 : data.name) === queueName) {
516
+ yield this.createQueue(data);
517
+ }
518
+ logger_1.Logger.info(`${data === null || data === void 0 ? void 0 : data.name} queue created `, 'findQueueAndExchange');
519
+ }
520
+ // Declare the exchange with dlx
521
+ for (let data of exchanges) {
522
+ if ((data === null || data === void 0 ? void 0 : data.name) === exchangeName) {
523
+ yield this.createExchange(data);
524
+ }
525
+ logger_1.Logger.info(`${data === null || data === void 0 ? void 0 : data.name} exchange created`, 'findQueueAndExchange');
526
+ }
527
+ // Declare the bindings for queues and exchanges with routing keys
528
+ for (let obj in bindings) {
529
+ (_a = bindings[obj]) === null || _a === void 0 ? void 0 : _a.forEach((key) => __awaiter(this, void 0, void 0, function* () {
530
+ if (obj === exchangeName && (key === null || key === void 0 ? void 0 : key.queue) === queueName) {
531
+ yield this.bindQueueAndExchanges(obj, key === null || key === void 0 ? void 0 : key.queue, key === null || key === void 0 ? void 0 : key.routingKey);
532
+ }
533
+ logger_1.Logger.info(`${key === null || key === void 0 ? void 0 : key.queue} bind with exchange name ${obj} and routing key ${key === null || key === void 0 ? void 0 : key.routingKey}`, 'findQueueAndExchange');
534
+ }));
535
+ }
536
+ }
537
+ catch (error) {
538
+ logger_1.Logger.error("Error on setup queues, exchanges and binding", 'findQueueAndExchange', error.message);
539
+ throw error;
540
+ }
541
+ });
542
+ }
543
+ /**
544
+ * Function to setup the queues and exchanges
545
+ * @params array
546
+ * @rtrun
547
+ */
548
+ setupQueuesAndExchanges() {
549
+ return __awaiter(this, void 0, void 0, function* () {
550
+ var _a;
551
+ logger_1.Logger.info('Reached to setupQueuesAndExchanges', 'setupQueuesAndExchanges');
552
+ try {
553
+ let exchanges = configData.exchanges;
554
+ let queues = configData.queues;
555
+ let bindings = configData.bindings;
556
+ // Declare the exchange with dlx
557
+ for (let data of exchanges) {
558
+ yield this.createExchange(data);
559
+ logger_1.Logger.info(`${data === null || data === void 0 ? void 0 : data.name} exchange created`, 'setupQueuesAndExchanges');
560
+ }
561
+ // Declare the queues with dlx
562
+ for (let data of queues) {
563
+ yield this.createQueue(data);
564
+ logger_1.Logger.info(`${data === null || data === void 0 ? void 0 : data.name} queue created `, 'setupQueuesAndExchanges');
565
+ }
566
+ // Declare the bindings for queues and exchanges with routing keys
567
+ for (let obj in bindings) {
568
+ (_a = bindings[obj]) === null || _a === void 0 ? void 0 : _a.forEach((key) => __awaiter(this, void 0, void 0, function* () {
569
+ yield this.bindQueueAndExchanges(obj, key === null || key === void 0 ? void 0 : key.queue, key === null || key === void 0 ? void 0 : key.routingKey);
570
+ logger_1.Logger.info(`${key === null || key === void 0 ? void 0 : key.queue} bind with exchange name ${obj} and routing key ${key === null || key === void 0 ? void 0 : key.routingKey}`, 'setupQueuesAndExchanges');
571
+ }));
572
+ }
573
+ }
574
+ catch (error) {
575
+ logger_1.Logger.error("Error on setup queues, exchanges and binding", 'setupQueuesAndExchanges', error.message);
576
+ }
577
+ });
578
+ }
579
+ ;
580
+ /**
581
+ * Function to binding queue and exchange
582
+ * @param exchangeName
583
+ * @param queueName
584
+ * @param routingKey
585
+ */
586
+ bindQueueAndExchanges(exchangeName, queueName, routingKey) {
587
+ return __awaiter(this, void 0, void 0, function* () {
588
+ try {
589
+ yield channel.bindQueue(queueName, exchangeName, routingKey, { 'toQueue': queueName, 'x-match': 'any' });
590
+ }
591
+ catch (error) {
592
+ logger_1.Logger.error('Error in bind Queue and exchange', 'bindQueueAndExchanges', { message: error.message });
593
+ }
594
+ });
595
+ }
596
+ /**
597
+ * Function to create the queue
598
+ * @param data
599
+ */
600
+ createQueue(data) {
601
+ return __awaiter(this, void 0, void 0, function* () {
602
+ try {
603
+ yield channel.assertQueue(data === null || data === void 0 ? void 0 : data.name, { durable: data.durable, exclusive: data.exclusive, autoDelete: data.autoDelete, arguments: data.arguments });
604
+ }
605
+ catch (error) {
606
+ logger_1.Logger.error('Error in Create Queue', 'createQueue', { message: error.message });
607
+ }
608
+ });
609
+ }
610
+ /**
611
+ * Function to create the exchange
612
+ * @param data
613
+ */
614
+ createExchange(data) {
615
+ return __awaiter(this, void 0, void 0, function* () {
616
+ try {
617
+ yield channel.assertExchange(data === null || data === void 0 ? void 0 : data.name, data.type, { durable: data.durable, autoDelete: data.autoDelete });
618
+ }
619
+ catch (error) {
620
+ logger_1.Logger.error('Error in Create exchange', 'createExchange', { message: error.message });
621
+ }
622
+ });
623
+ }
624
+ // private async publishMessageRetryQueue(request: PublishMessageInputType, attempt: number) {
625
+ // try {
626
+ // Logger.error(`Failed to publish message. Attempt ${attempt} of ${maxRetries}. Error:`, 'publishMessageRetryQueue', request);
627
+ // let queueName = (request as PublishMessageInputType)?.queueName
628
+ // const data: MessageModel = (request as PublishMessageInputType)?.message;
629
+ // if (typeof data.message === 'object' && data.message !== null) {
630
+ // (data.message as { retries: number }).retries = attempt;
631
+ // }
632
+ // // Wait before retrying (Exponential Backoff)
633
+ // let retryDelay: number;
634
+ // retryDelay = Number(retry_delay[attempt]);
635
+ // let count:any = retry_delay.length - 1 === attempt?retry_delay[retry_delay.length - 1]:retry_delay[attempt];
636
+ // retryDelay = Number(count);
637
+ // await this.sendMessageToRetryQueue(attempt, data, retryDelay, queueName);
638
+ // Logger.info(`Retrying in ${retryDelay / 1000}, seconds...`, 'publishMessageRetryQueue');
639
+ // await new Promise((resolve) => setTimeout(resolve, retryDelay));
640
+ // } catch (error) {
641
+ // Logger.error(`Failed to publish message. Attempt ${attempt} of ${maxRetries}. Error:`, 'publishMessageRetryQueue', request);
642
+ // throw error;
643
+ // }
644
+ // }
645
+ /**
646
+ * Function to connect create to RabbitMQ
647
+ */
648
+ createConnection() {
649
+ return __awaiter(this, void 0, void 0, function* () {
650
+ try {
651
+ logger_1.Logger.info('Reached to createConnection', 'createConnection');
652
+ configManager.loadConfig(RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.CONFIG_PATH);
653
+ let url = `amqp://${RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.USER}:${RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.PASS}@${RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.HOST}`;
654
+ // Create a connection to RabbitMQ server
655
+ connection = yield amqp.connect(url, { heartbeat: RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.HEARTBEAT });
656
+ isConnectionOpen = true;
657
+ // check the connection status
658
+ this.bindConnectionEventHandler();
659
+ // create channel
660
+ channel = yield connection.createConfirmChannel();
661
+ channel.prefetch(RABBITMQ === null || RABBITMQ === void 0 ? void 0 : RABBITMQ.PREFETCH_COUNT);
662
+ logger_1.Logger.info('RabbitMQ connected successfully! ', 'createConnection');
663
+ // create exchange and queue and bind with exchange
664
+ yield this.setupQueuesAndExchanges();
665
+ const connectionWrapper = { connection, channel };
666
+ return connectionWrapper;
667
+ }
668
+ catch (error) {
669
+ // Log and rethrow any errors that occur during connection
670
+ logger_1.Logger.error('Failed to connect to RabbitMQ', 'connection', error === null || error === void 0 ? void 0 : error.message);
671
+ return { connection: null, channel: null };
672
+ }
673
+ });
674
+ }
675
+ /**
676
+ * Function for bind connection event handler on close and error setupQueuesAndExchanges
677
+ * @returns
678
+ */
679
+ bindConnectionEventHandler() {
680
+ try {
681
+ connection.on('close', (err) => __awaiter(this, void 0, void 0, function* () {
682
+ logger_1.Logger.error(`RabbitMQ: bindConnectionEventHandler:close`, `Connection closed`, err);
683
+ isConnectionOpen = false;
684
+ if (connectionRetry <= maxRetries) {
685
+ yield this.createConnection();
686
+ connectionRetry++;
687
+ }
688
+ }));
689
+ connection.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
690
+ logger_1.Logger.error(`RabbitMQ: bindConnectionEventHandler:error`, `Connection error`, err);
691
+ isConnectionOpen = false;
692
+ if (connectionRetry <= maxRetries) {
693
+ yield this.createConnection();
694
+ connectionRetry++;
695
+ }
696
+ }));
697
+ return isConnectionOpen;
698
+ }
699
+ catch (error) {
700
+ isConnectionOpen = false;
701
+ return isConnectionOpen;
702
+ }
703
+ }
704
+ }
705
+ exports.MessageBrokerClient = MessageBrokerClient;
706
+ //# sourceMappingURL=MessageBrokerClient.js.map