UNPKG

redis-smq

Version:

A simple high-performance Redis message queue for Node.js.

175 lines 8.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageHandlerRunner = void 0; const redis_smq_common_1 = require("redis-smq-common"); const index_js_1 = require("../../../config/index.js"); const index_js_2 = require("../errors/index.js"); const message_handler_js_1 = require("../message-handler/message-handler/message-handler.js"); const event_bus_publisher_js_1 = require("./event-bus-publisher.js"); class MessageHandlerRunner extends redis_smq_common_1.Runnable { constructor(consumer, redisClient, eventBus) { super(); this.messageHandlerInstances = []; this.messageHandlers = []; this.runMessageHandlers = (cb) => { const handlerCount = this.messageHandlers.length; this.logger.info(`Starting ${handlerCount} message handler(s)`); if (handlerCount === 0) return cb(); redis_smq_common_1.async.each(this.messageHandlers, (handlerParams, _, done) => { this.runMessageHandler(handlerParams, done); }, (err) => { if (err) { this.logger.error(`Error starting message handlers: ${err.message}`); } else { this.logger.info(`All message handlers started`); } cb(err); }); }; this.shutDownMessageHandlers = (cb) => { const handlerCount = this.messageHandlerInstances.length; this.logger.info(`Shutting down ${handlerCount} message handler(s)`); if (handlerCount === 0) return cb(); redis_smq_common_1.async.each(this.messageHandlerInstances, (handler, _, done) => { this.shutdownMessageHandler(handler, done); }, () => { this.messageHandlerInstances = []; this.logger.info('All message handlers have been shut down'); cb(); }); }; this.consumer = consumer; this.redisClient = redisClient; this.logger = redis_smq_common_1.logger.getLogger(index_js_1.Configuration.getSetConfig().logger, this.constructor.name.toLowerCase()); this.logger.info(`Initializing MessageHandlerRunner with ID: ${this.id}`); this.eventBus = eventBus; if (this.eventBus) { this.logger.debug('Event bus provided, setting up event bus publisher'); (0, event_bus_publisher_js_1.eventBusPublisher)(this, this.eventBus, this.logger); } this.logger.debug(`MessageHandlerRunner initialized for consumer ID: ${this.consumer.getId()}`); } getLogger() { return this.logger; } getMessageHandlerInstance(queue) { return this.messageHandlerInstances.find((i) => { const handlerQueue = i.getQueue(); return (handlerQueue.queueParams.name === queue.queueParams.name && handlerQueue.queueParams.ns === queue.queueParams.ns && handlerQueue.groupId === queue.groupId); }); } getMessageHandler(queue) { return this.messageHandlers.find((i) => i.queue.queueParams.name === queue.queueParams.name && i.queue.queueParams.ns === queue.queueParams.ns && i.queue.groupId === queue.groupId); } createMessageHandlerInstance(handlerParams) { const instance = new message_handler_js_1.MessageHandler(this.consumer, this.redisClient, handlerParams, true, this.eventBus); instance.on('consumer.messageHandler.error', (err, consumerId, queue) => { this.logger.error(`MessageHandler error from consumer ${consumerId} for queue ${JSON.stringify(queue)}: ${err.message}`); this.removeMessageHandler(queue, () => { this.logger.error(`Error in MessageHandler: ${err.message}`, err); }); }); this.messageHandlerInstances.push(instance); this.logger.info(`Created MessageHandler (ID: ${instance.getId()}) for queue: ${handlerParams.queue.queueParams.name}. Total: ${this.messageHandlerInstances.length}`); return instance; } runMessageHandler(handlerParams, cb) { const handler = this.createMessageHandlerInstance(handlerParams); handler.run((err) => { if (err) { this.logger.error(`Failed to run message handler: ${err.message}`); this.removeMessageHandler(handlerParams.queue, () => cb(err)); } else { this.logger.debug(`Message handler started for queue: ${handlerParams.queue.queueParams.name}`); cb(); } }); } shutdownMessageHandler(messageHandler, cb) { const queue = messageHandler.getQueue(); messageHandler.shutdown((err) => { if (err) { this.logger.warn(`Error during message handler shutdown (ignored): ${err.message}`); } const beforeCount = this.messageHandlerInstances.length; this.messageHandlerInstances = this.messageHandlerInstances.filter((handler) => { const iQueue = handler.getQueue(); return !(iQueue.queueParams.name === queue.queueParams.name && iQueue.queueParams.ns === queue.queueParams.ns && iQueue.groupId === queue.groupId); }); const afterCount = this.messageHandlerInstances.length; this.logger.debug(`Removed ${beforeCount - afterCount} message handler instance(s). Remaining: ${afterCount}`); cb(); }); } goingUp() { this.logger.info('MessageHandlerRunner going up'); return super.goingUp().concat([this.runMessageHandlers]); } goingDown() { this.logger.info('MessageHandlerRunner going down'); return [this.shutDownMessageHandlers].concat(super.goingDown()); } handleError(err) { if (this.isRunning()) { this.logger.error(`MessageHandlerRunner error: ${err.message}`, err); this.emit('consumer.messageHandlerRunner.error', err, this.consumer.getId()); } super.handleError(err); } removeMessageHandler(queue, cb) { const handler = this.getMessageHandler(queue); if (!handler) { this.logger.debug(`No message handler found for queue: ${queue.queueParams.name}, nothing to remove`); return cb(); } const beforeCount = this.messageHandlers.length; this.messageHandlers = this.messageHandlers.filter((h) => { const q = h.queue; return !(queue.queueParams.name === q.queueParams.name && queue.queueParams.ns === q.queueParams.ns && queue.groupId === q.groupId); }); const afterCount = this.messageHandlers.length; this.logger.info(`Message handler for queue (${queue.queueParams.name}) removed. Removed ${beforeCount - afterCount} configuration(s).`); const handlerInstance = this.getMessageHandlerInstance(queue); if (handlerInstance) { this.shutdownMessageHandler(handlerInstance, cb); } else { cb(); } } addMessageHandler(queue, messageHandler, cb) { if (this.getMessageHandler(queue)) { this.logger.warn(`Message handler for queue ${queue.queueParams.name} already exists`); return cb(new index_js_2.ConsumerConsumeMessageHandlerAlreadyExistsError()); } const handlerParams = { queue, messageHandler, }; this.messageHandlers.push(handlerParams); this.logger.info(`Message handler registered for queue: ${queue.queueParams.name}. Total handlers: ${this.messageHandlers.length}`); if (this.isRunning()) { this.runMessageHandler(handlerParams, cb); } else { cb(); } } getQueues() { return this.messageHandlers.map((i) => i.queue); } } exports.MessageHandlerRunner = MessageHandlerRunner; //# sourceMappingURL=message-handler-runner.js.map