UNPKG

redis-smq

Version:

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

216 lines 9.6 kB
import { async, CallbackEmptyReplyError, createLogger, } from 'redis-smq-common'; import { Configuration } from '../config-manager/configuration.js'; import { _deleteMessage } from './_/_delete-message.js'; import { _getMessageState } from './_/_get-message-state.js'; import { _getMessageStatus } from './_/_get-message-status.js'; import { _getMessage, _getMessages } from './_/_get-message.js'; import { _requeueMessage } from './_/_requeue-message.js'; import { withSharedPoolConnection } from '../common/redis/redis-connection-pool/with-shared-pool-connection.js'; import { redisKeys } from '../common/redis/redis-keys/redis-keys.js'; import { MessageNotFoundError, UnacknowledgmentHistoryDisabledError, } from '../errors/index.js'; export class MessageManager { logger; constructor() { const config = Configuration.getConfig(); this.logger = createLogger(config.logger, this.constructor.name); } getMessageStatus(messageId, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting message status', { messageId }); withSharedPoolConnection((client, cb) => { _getMessageStatus(client, messageId, (err, status) => { if (err) { this.logger.error('Failed to get message status', { messageId, error: err.message, }); cb(err); } else { this.logger.debug('Successfully retrieved message status', { messageId, status, }); cb(null, status); } }); }, callback); }); } getMessageState(messageId, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting message state', { messageId }); withSharedPoolConnection((client, cb) => { _getMessageState(client, messageId, (err, state) => { if (err) { this.logger.error('Failed to get message state', { messageId, error: err.message, }); cb(err); } else { this.logger.debug('Successfully retrieved message state', { messageId, }); cb(null, state?.toJSON()); } }); }, callback); }); } getMessagesByIds(messageIds, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting messages by IDs', { messageCount: messageIds.length, }); withSharedPoolConnection((client, cb) => { _getMessages(client, messageIds, (err, reply) => { if (err) { this.logger.error('Failed to get messages', { error: err.message }); cb(err); } else if (!reply) { this.logger.error('Empty messages reply'); cb(new CallbackEmptyReplyError()); } else { this.logger.debug('Successfully retrieved messages', { messageCount: reply.length, }); cb(null, reply.map((i) => i.transfer())); } }); }, callback); }); } getMessageById(messageId, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting message by ID', { messageId }); withSharedPoolConnection((client, cb) => { _getMessage(client, messageId, (err, reply) => { if (err) { this.logger.error('Failed to get message', { messageId, error: err.message, }); cb(err); } else if (!reply) { this.logger.error('Empty message reply', { messageId }); cb(new CallbackEmptyReplyError()); } else { this.logger.debug('Successfully retrieved message', { messageId }); cb(null, reply.transfer()); } }); }, callback); }); } deleteMessagesByIds(ids, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug(`Deleting ${ids.length} messages by IDs`, { messageIds: ids, }); withSharedPoolConnection((client, cb) => { async.withCallback((cb) => _deleteMessage(client, ids, null, cb), (reply, cb) => { this.logger.debug('MessageList deletion completed', reply); cb(null, reply); }, cb); }, (err, result) => { if (err) { this.logger.error('Failed to delete messages by IDs', { error: err.message, messageIds: ids, }); } callback(err, result); }); }); } deleteMessageById(id, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Deleting message by ID', { messageId: id }); this.deleteMessagesByIds([id], (err, reply) => { if (err) { this.logger.error('Failed to delete message', { messageId: id, error: err.message, }); callback(err); } else { this.logger.debug('Successfully deleted message', { messageId: id }); callback(null, reply); } }); }); } requeueMessageById(messageId, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Requeuing message by ID', { messageId }); withSharedPoolConnection((client, cb) => { _requeueMessage(client, messageId, (err, newMessageId) => { if (err) { this.logger.error('Failed to requeue message', { messageId, error: err.message, }); return cb(err); } if (!newMessageId) return cb(new CallbackEmptyReplyError()); this.logger.debug(`Successfully requeued message ${messageId}. New message ID is ${newMessageId}`); cb(null, newMessageId); }); }, callback); }); } getMessageUnacknowledgementHistory(messageId, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting message unacknowledgement history', messageId); if (!Configuration.getConfig().messageAudit.unacknowledgementHistory.enabled) { this.logger.debug('Message unacknowledgement history is disabled'); return callback(new UnacknowledgmentHistoryDisabledError()); } const { keyMessage, keyMessageUnacknowledgementHistory } = redisKeys.getMessageKeys(messageId); withSharedPoolConnection((client, done) => { async.waterfall([ (cb) => { client.exists(keyMessage, (err, exists) => { if (err) { this.logger.error('Failed to check message existence', { messageId, error: err.message, }); return cb(err); } if (!exists) return cb(new MessageNotFoundError()); cb(); }); }, (_, cb) => { client.lrange(keyMessageUnacknowledgementHistory, 0, -1, (err, records) => { if (err) { this.logger.error('Failed to get message history', { messageId, error: err.message, }); return cb(err); } const history = records?.map((record) => JSON.parse(record)) || []; this.logger.debug('Successfully retrieved message history', { messageId, recordCount: history.length, }); cb(null, history); }); }, ], done); }, callback); }); } } //# sourceMappingURL=message-manager.js.map