UNPKG

redis-smq

Version:

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

181 lines 8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConsumeMessage = void 0; const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const redis_smq_common_1 = require("redis-smq-common"); const scripts_js_1 = require("../../../../common/redis-client/scripts/scripts.js"); const redis_keys_js_1 = require("../../../../common/redis-keys/redis-keys.js"); const index_js_1 = require("../../../../config/index.js"); const index_js_2 = require("../../../message/index.js"); const index_js_3 = require("../../types/index.js"); const index_js_4 = require("../errors/index.js"); const processing_queue_js_1 = require("../processing-queue/processing-queue.js"); const event_bus_publisher_js_1 = require("./event-bus-publisher.js"); class ConsumeMessage extends redis_smq_common_1.Runnable { constructor(redisClient, consumer, queue, messageHandlerId, messageHandler, logger, eventBus) { super(); this.consumeMessageWorker = null; this.validateMessageHandler = (cb) => { if (typeof this.messageHandler === 'string') { if (!['.js', '.cjs'].includes(path_1.default.extname(this.messageHandler))) { cb(new index_js_4.ConsumerMessageHandlerFilenameExtensionError()); } else (0, fs_1.stat)(this.messageHandler, (err) => { if (err) cb(new index_js_4.ConsumerMessageHandlerFileError()); else cb(); }); } else cb(); }; this.queue = queue; this.consumerId = consumer.getId(); this.messageHandler = messageHandler; this.messageHandlerId = messageHandlerId; this.redisClient = redisClient; const { keyQueueProcessing } = redis_keys_js_1.redisKeys.getQueueConsumerKeys(this.queue.queueParams, this.consumerId); const { keyQueueAcknowledged } = redis_keys_js_1.redisKeys.getQueueKeys(this.queue.queueParams, this.queue.groupId); this.keyQueueAcknowledged = keyQueueAcknowledged; this.keyQueueProcessing = keyQueueProcessing; this.logger = logger; if (eventBus) { (0, event_bus_publisher_js_1.eventBusPublisher)(this, eventBus, logger); } } getLogger() { return this.logger; } acknowledgeMessage(message) { const messageId = message.getId(); const { store, queueSize, expire } = index_js_1.Configuration.getSetConfig().messages.store.acknowledged; const { keyMessage } = redis_keys_js_1.redisKeys.getMessageKeys(messageId); const redisClient = this.redisClient.getInstance(); if (redisClient instanceof Error) { this.handleError(redisClient); return void 0; } redisClient.runScript(scripts_js_1.ELuaScriptName.ACKNOWLEDGE_MESSAGE, [this.keyQueueProcessing, this.keyQueueAcknowledged, keyMessage], [ index_js_2.EMessageProperty.STATUS, index_js_2.EMessagePropertyStatus.ACKNOWLEDGED, Number(store), expire, queueSize * -1, ], (err) => { if (err) this.handleError(err); else { this.emit('consumer.consumeMessage.messageAcknowledged', messageId, this.queue, this.messageHandlerId, this.consumerId); } }); } unacknowledgeMessage(msg, unknowledgmentReason) { const redisClient = this.redisClient.getInstance(); if (redisClient instanceof Error) { this.handleError(redisClient); return void 0; } processing_queue_js_1.processingQueue.unknowledgeMessage(redisClient, this.consumerId, [this.queue.queueParams], this.logger, unknowledgmentReason, (err, reply) => { if (err) this.handleError(err); else if (!reply) this.handleError(new redis_smq_common_1.CallbackEmptyReplyError()); else { const messageId = msg.getId(); this.emit('consumer.consumeMessage.messageUnacknowledged', messageId, this.queue, this.messageHandlerId, this.consumerId, unknowledgmentReason); const unknowledgment = reply[messageId]; if (unknowledgment.action === index_js_3.EMessageUnknowledgmentAction.DEAD_LETTER) { this.emit('consumer.consumeMessage.messageDeadLettered', messageId, this.queue, this.messageHandlerId, this.consumerId, unknowledgment.deadLetterReason); } else if (unknowledgment.action === index_js_3.EMessageUnknowledgmentAction.DELAY) { this.emit('consumer.consumeMessage.messageDelayed', messageId, this.queue, this.messageHandlerId, this.consumerId); } else { this.emit('consumer.consumeMessage.messageRequeued', messageId, this.queue, this.messageHandlerId, this.consumerId); } } }); } getConsumeMessageWorker(messageHandlerFilename) { if (!this.consumeMessageWorker) { this.consumeMessageWorker = new redis_smq_common_1.WorkerCallable(messageHandlerFilename); } return this.consumeMessageWorker; } invokeMessageHandler(messageHandler, msg, cb) { if (typeof messageHandler === 'string') { this.getConsumeMessageWorker(messageHandler).call(msg, cb); } else messageHandler(msg, cb); } consumeMessage(msg) { let isTimeout = false; let timer = null; try { const consumeTimeout = msg.producibleMessage.getConsumeTimeout(); if (consumeTimeout) { timer = setTimeout(() => { isTimeout = true; timer = null; this.unacknowledgeMessage(msg, index_js_3.EMessageUnknowledgmentReason.TIMEOUT); }, consumeTimeout); } const onConsumed = (err) => { if (this.isRunning() && !isTimeout) { if (timer) clearTimeout(timer); if (err) { this.logger.error(err); this.unacknowledgeMessage(msg, index_js_3.EMessageUnknowledgmentReason.UNACKNOWLEDGED); } else { this.acknowledgeMessage(msg); } } }; this.invokeMessageHandler(this.messageHandler, msg.transfer(), onConsumed); } catch (error) { this.logger.error(error); this.unacknowledgeMessage(msg, index_js_3.EMessageUnknowledgmentReason.CONSUME_ERROR); } } goingUp() { return super .goingUp() .concat([this.redisClient.init, this.validateMessageHandler]); } goingDown() { return [ (cb) => { if (this.consumeMessageWorker) { this.consumeMessageWorker.shutdown(cb); } else cb(); }, ].concat(super.goingDown()); } handleError(err) { this.emit('consumer.consumeMessage.error', err, this.consumerId, this.queue); super.handleError(err); } handleReceivedMessage(message) { if (this.isRunning()) { if (message.getSetExpired()) { this.unacknowledgeMessage(message, index_js_3.EMessageUnknowledgmentReason.TTL_EXPIRED); } else this.consumeMessage(message); } } } exports.ConsumeMessage = ConsumeMessage; //# sourceMappingURL=consume-message.js.map