UNPKG

redis-smq

Version:

A high-performance, reliable, and scalable message queue for Node.js.

95 lines 3.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageAcknowledger = void 0; const redis_smq_common_1 = require("redis-smq-common"); const _execute_acknowledgement_script_js_1 = require("./_/_execute-acknowledgement-script.js"); class MessageAcknowledger extends redis_smq_common_1.Runnable { constructor(queue, consumerId, logger, consumerOptions) { super(); this.pending = []; this.timer = null; this.pendingCallbacks = []; this.queue = queue; this.consumerId = consumerId; this.logger = logger.createLogger(this.constructor.name); const { enabled, batchTimeoutMs, batchSize } = consumerOptions.batchAcks; this.useBatchAcks = enabled; this.batchSize = batchSize; this.batchTimeoutMs = batchTimeoutMs; } add(message) { const messageId = message.getId(); if (!this.isOperational()) { this.logger.warn(`Rejecting message ${messageId} - MessageAcknowledger is not operational`); return; } if (!this.useBatchAcks) { const messages = [message]; (0, _execute_acknowledgement_script_js_1._executeAcknowledgementScript)(this.queue, this.consumerId, messages, (err, result) => this.handleAcknowledgementResult(err, result, messages)); return; } this.pending.push(message); this.logger.debug(`Queued message ${messageId} for batch. Queue size: ${this.pending.length}`); if (this.pending.length >= this.batchSize) { this.flush(); } else if (!this.timer) { this.timer = setTimeout(() => this.flush(), this.batchTimeoutMs); } } flush(cb) { if (this.timer) { clearTimeout(this.timer); this.timer = null; } if (this.pending.length === 0) { if (cb) cb(); return; } if (cb) this.pendingCallbacks.push(cb); const batch = [...this.pending]; this.pending = []; this.logger.debug(`Flushing batch of ${batch.length} acknowledgments`); (0, _execute_acknowledgement_script_js_1._executeAcknowledgementScript)(this.queue, this.consumerId, batch, (err, result) => { this.handleAcknowledgementResult(err, result, batch); const callbacks = [...this.pendingCallbacks]; this.pendingCallbacks = []; callbacks.forEach((callback) => callback()); }); } goingDown() { return [ (cb) => { this.logger.info(`Shutting down with ${this.pending.length} pending acknowledgments`); this.flush(cb); }, ]; } handleAcknowledgementResult(err, result, messages) { if (err) { this.logger.error(`Message acknowledgement failed due to: ${err}`); this.handleError(err); return; } if (!result) { this.handleError(new redis_smq_common_1.CallbackEmptyReplyError({ message: `_executeAcknowledgementScript() returned an empty result.`, })); return; } result.forEach((result, index) => { const message = messages[index]; const messageId = message.getId(); if (result === 0) { this.logger.info(`Message ${messageId} was already acknowledged or something else`); return; } this.logger.debug(`Message ${messageId} acknowledged successfully`); this.emit('messageAcknowledger.messageAcknowledged', message); }); } } exports.MessageAcknowledger = MessageAcknowledger; //# sourceMappingURL=message-acknowledger.js.map