UNPKG

redis-smq

Version:

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

214 lines 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueMessagesManagerAbstract = void 0; const redis_smq_common_1 = require("redis-smq-common"); const redis_keys_js_1 = require("../../../common/redis-keys/redis-keys.js"); const index_js_1 = require("../../../config/index.js"); const _delete_message_js_1 = require("../../message/_/_delete-message.js"); const _parse_queue_extended_params_js_1 = require("../../queue/_/_parse-queue-extended-params.js"); const _validate_queue_extended_params_js_1 = require("../_/_validate-queue-extended-params.js"); class QueueMessagesManagerAbstract { constructor(redisClient, messagesStorage, message, redisKey) { this.requireGroupId = false; this.redisClient = redisClient; this.messageStorage = messagesStorage; this.message = message; this.redisKey = redisKey; this.logger = redis_smq_common_1.logger.getLogger(index_js_1.Configuration.getSetConfig().logger, this.constructor.name.toLowerCase()); this.redisClient.on('error', (err) => this.logger.error(err)); } getTotalPages(pageSize, totalItems) { if (pageSize <= 0) { return 1; } const totalPages = Math.ceil(totalItems / pageSize); return totalPages > 0 ? totalPages : 1; } getPaginationParams(cursor, totalItems, pageSize) { const totalPages = this.getTotalPages(pageSize, totalItems); const currentPage = cursor < 1 || cursor > totalPages ? 1 : cursor; const offsetStart = (currentPage - 1) * pageSize; const offsetEnd = offsetStart + pageSize - 1; return { offsetStart, offsetEnd, currentPage, totalPages, pageSize }; } getMessagesIds(queue, page, pageSize, cb) { this.logger.debug(`Getting message IDs for queue ${queue.queueParams.name}, page ${page}, size ${pageSize}`); const keys = redis_keys_js_1.redisKeys.getQueueKeys(queue.queueParams, queue.groupId); const keyVal = keys[this.redisKey]; redis_smq_common_1.async.waterfall([ (next) => { this.logger.debug(`Counting messages for queue ${queue.queueParams.name}`); this.messageStorage.count(keyVal, next); }, (totalItems, next) => { this.logger.debug(`Found ${totalItems} total messages for queue ${queue.queueParams.name}`); const { currentPage, offsetStart, offsetEnd, totalPages } = this.getPaginationParams(page, totalItems, pageSize); const nextCursor = currentPage < totalPages ? currentPage + 1 : 0; if (totalItems === 0) { this.logger.debug(`No messages found for queue ${queue.queueParams.name}`); return next(null, { cursor: nextCursor, totalItems, items: [], }); } this.logger.debug(`Fetching messages for queue ${queue.queueParams.name} from index ${offsetStart} to ${offsetEnd}`); this.messageStorage.fetchItems(keyVal, { page: currentPage, pageSize, offsetStart, offsetEnd }, (err, items) => { if (err) { this.logger.error(`Error fetching messages: ${err.message}`); return next(err); } this.logger.debug(`Retrieved ${(items === null || items === void 0 ? void 0 : items.length) || 0} messages for queue ${queue.queueParams.name}`); next(null, { cursor: nextCursor, totalItems, items: items !== null && items !== void 0 ? items : [], }); }); }, ], (err, result) => { if (err) { this.logger.error(`Error in getMessagesIds: ${err.message}`); } cb(err, result); }); } purge(queue, cb) { const parsedParams = (0, _parse_queue_extended_params_js_1._parseQueueExtendedParams)(queue); if (parsedParams instanceof Error) { this.logger.error(`Error parsing queue parameters: ${parsedParams.message}`); return cb(parsedParams); } this.logger.info(`Purging messages from queue ${parsedParams.queueParams.name}`); (0, redis_smq_common_1.withRedisClient)(this.redisClient, (client, cb) => { (0, _validate_queue_extended_params_js_1._validateQueueExtendedParams)(client, parsedParams, this.requireGroupId, (err) => { if (err) { this.logger.error(`Error validating queue parameters: ${err.message}`); return cb(err); } this._purgeMessages(client, parsedParams, cb); }); }, cb); } _purgeMessages(client, parsedParams, cb) { this.logger.debug(`Starting batch purge for queue ${parsedParams.queueParams.name}`); const purgeBatch = (cursor = '0') => { this.logger.debug(`Processing purge batch with cursor ${cursor} for queue ${parsedParams.queueParams.name}`); redis_smq_common_1.async.waterfall([ (next) => { this.getMessagesIds(parsedParams, Number(cursor), 1000, next); }, (page, next) => { const { items, cursor: nextCursor } = page; if (items.length === 0) { this.logger.debug(`No messages to purge in this batch for queue ${parsedParams.queueParams.name}`); return next(null, String(nextCursor)); } this.logger.debug(`Deleting batch of ${items.length} messages from queue ${parsedParams.queueParams.name}`); (0, _delete_message_js_1._deleteMessage)(client, items, (err, reply) => { if (err) { this.logger.error(`Error deleting messages: ${err.message}`); return next(err); } this.logger.debug('Messages deletion completed', reply); next(null, String(nextCursor)); }); }, ], (err, nextCursor) => { if (err) { this.logger.error(`Error in purge batch: ${err.message}`); return cb(err); } if (nextCursor !== '0') { this.logger.debug(`More messages to purge, continuing with cursor ${nextCursor} for queue ${parsedParams.queueParams.name}`); purgeBatch(String(nextCursor)); } else { this.logger.info(`Successfully purged all messages from queue ${parsedParams.queueParams.name}`); cb(); } }); }; purgeBatch('0'); } getMessages(queue, page, pageSize, cb) { const parsedParams = (0, _parse_queue_extended_params_js_1._parseQueueExtendedParams)(queue); if (parsedParams instanceof Error) { this.logger.error(`Error parsing queue parameters: ${parsedParams.message}`); return cb(parsedParams); } this.logger.debug(`Getting messages for queue ${parsedParams.queueParams.name}, page ${page}, size ${pageSize}`); (0, redis_smq_common_1.withRedisClient)(this.redisClient, (client, cb) => { (0, _validate_queue_extended_params_js_1._validateQueueExtendedParams)(client, parsedParams, this.requireGroupId, (err) => { if (err) { this.logger.error(`Error validating queue parameters: ${err.message}`); return cb(err); } redis_smq_common_1.async.withCallback((cb) => this.getMessagesIds(parsedParams, page, pageSize, cb), (pageResult, cb) => { if (pageResult.items.length === 0) { this.logger.debug(`No messages found for queue ${parsedParams.queueParams.name} on page ${page}`); return cb(null, Object.assign(Object.assign({}, pageResult), { items: [] })); } this.logger.debug(`Retrieving ${pageResult.items.length} message details for queue ${parsedParams.queueParams.name}`); this.message.getMessagesByIds(pageResult.items, (err, messages) => { if (err) { this.logger.error(`Error getting message details: ${err.message}`); return cb(err); } this.logger.debug(`Successfully retrieved ${(messages === null || messages === void 0 ? void 0 : messages.length) || 0} message details for queue ${parsedParams.queueParams.name}`); cb(null, Object.assign(Object.assign({}, pageResult), { items: messages !== null && messages !== void 0 ? messages : [] })); }); }, cb); }); }, cb); } countMessages(queue, cb) { const parsedParams = (0, _parse_queue_extended_params_js_1._parseQueueExtendedParams)(queue); if (parsedParams instanceof Error) { this.logger.error(`Error parsing queue parameters: ${parsedParams.message}`); return cb(parsedParams); } this.logger.debug(`Counting messages for queue ${parsedParams.queueParams.name}`); (0, redis_smq_common_1.withRedisClient)(this.redisClient, (client, cb) => { (0, _validate_queue_extended_params_js_1._validateQueueExtendedParams)(client, parsedParams, this.requireGroupId, (err) => { if (err) { this.logger.error(`Error validating queue parameters: ${err.message}`); return cb(err); } const keys = redis_keys_js_1.redisKeys.getQueueKeys(parsedParams.queueParams, parsedParams.groupId); const keyVal = keys[this.redisKey]; this.messageStorage.count(keyVal, (err, count) => { if (err) { this.logger.error(`Error counting messages: ${err.message}`); return cb(err); } this.logger.debug(`Queue ${parsedParams.queueParams.name} has ${count} messages`); cb(null, count); }); }); }, cb); } shutdown(cb) { this.logger.info('Shutting down queue messages manager'); redis_smq_common_1.async.series([ (next) => { this.logger.debug('Shutting down message handler'); this.message.shutdown(next); }, (next) => { this.logger.debug('Shutting down Redis client'); this.redisClient.shutdown(next); }, ], (err) => { if (err) { this.logger.error(`Error during shutdown: ${err.message}`); } else { this.logger.info('Queue messages manager shutdown complete'); } cb(err); }); } } exports.QueueMessagesManagerAbstract = QueueMessagesManagerAbstract; //# sourceMappingURL=queue-messages-manager-abstract.js.map