UNPKG

redis-smq

Version:

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

216 lines 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueConsumerGroupsCache = void 0; const redis_smq_common_1 = require("redis-smq-common"); const index_js_1 = require("../../config/index.js"); const _get_consumer_groups_js_1 = require("../consumer-groups/_/_get-consumer-groups.js"); const _get_queue_properties_js_1 = require("../queue/_/_get-queue-properties.js"); const _get_queues_js_1 = require("../queue/_/_get-queues.js"); const index_js_2 = require("../queue/index.js"); class QueueConsumerGroupsCache extends redis_smq_common_1.Runnable { constructor(producer, redisClient, eventBus) { super(); this.consumerGroupsByQueues = {}; this.addConsumerGroup = (queue, groupId) => { const queueKey = `${queue.name}@${queue.ns}`; this.logger.debug(`Adding consumer group ${groupId} to queue ${queueKey}`); this.consumerGroupsByQueues[queueKey] = this.consumerGroupsByQueues[queueKey] || []; const group = this.consumerGroupsByQueues[queueKey]; if (!group.includes(groupId)) { this.logger.debug(`Consumer group ${groupId} not found in queue ${queueKey}, adding it`); group.push(groupId); } else { this.logger.debug(`Consumer group ${groupId} already exists in queue ${queueKey}, skipping`); } }; this.deleteConsumerGroup = (queue, groupId) => { const queueKey = `${queue.name}@${queue.ns}`; this.logger.debug(`Deleting consumer group ${groupId} from queue ${queueKey}`); const groups = this.consumerGroupsByQueues[queueKey]; if (groups && groups.includes(groupId)) { this.logger.debug(`Found consumer group ${groupId} in queue ${queueKey}, removing it`); this.consumerGroupsByQueues[queueKey] = groups.filter((i) => i !== groupId); this.logger.debug(`Queue ${queueKey} now has ${this.consumerGroupsByQueues[queueKey].length} consumer groups`); } else { this.logger.debug(`Consumer group ${groupId} not found in queue ${queueKey}, nothing to delete`); } }; this.addQueue = (queue, properties) => { const queueKey = `${queue.name}@${queue.ns}`; this.logger.debug(`Adding queue ${queueKey} with delivery model ${index_js_2.EQueueDeliveryModel[properties.deliveryModel]}`); if (properties.deliveryModel === index_js_2.EQueueDeliveryModel.PUB_SUB) { this.logger.debug(`Queue ${queueKey} is PUB_SUB, initializing empty consumer groups array`); this.consumerGroupsByQueues[queueKey] = []; } else { this.logger.debug(`Queue ${queueKey} is not PUB_SUB, skipping consumer groups initialization`); } }; this.deleteQueue = (queue) => { const queueKey = `${queue.name}@${queue.ns}`; this.logger.debug(`Deleting queue ${queueKey} from consumer groups cache`); if (this.consumerGroupsByQueues[queueKey]) { this.logger.debug(`Found queue ${queueKey} in cache, removing it`); delete this.consumerGroupsByQueues[queueKey]; } else { this.logger.debug(`Queue ${queueKey} not found in cache, nothing to delete`); } }; this.subscribe = (cb) => { this.logger.debug('Subscribing to queue events'); const instance = this.eventBus.getInstance(); if (instance instanceof Error) { this.logger.error('Failed to get event bus instance', instance); cb(instance); } else { this.logger.debug('Successfully got event bus instance, registering event handlers'); instance.on('queue.queueCreated', this.addQueue); instance.on('queue.queueDeleted', this.deleteQueue); instance.on('queue.consumerGroupCreated', this.addConsumerGroup); instance.on('queue.consumerGroupDeleted', this.deleteConsumerGroup); this.logger.info('Successfully subscribed to all queue events'); cb(); } }; this.unsubscribe = (cb) => { this.logger.debug('Unsubscribing from queue events'); const instance = this.eventBus.getInstance(); if (instance instanceof Error) { this.logger.error('Failed to get event bus instance', instance); cb(instance); } else { this.logger.debug('Successfully got event bus instance, removing event handlers'); instance.removeListener('queue.queueCreated', this.addQueue); instance.removeListener('queue.queueDeleted', this.deleteQueue); instance.removeListener('queue.consumerGroupCreated', this.addConsumerGroup); instance.removeListener('queue.consumerGroupDeleted', this.deleteConsumerGroup); this.logger.info('Successfully unsubscribed from all queue events'); cb(); } }; this.loadConsumerGroups = (cb) => { this.logger.debug('Loading consumer groups for all queues'); const redisClient = this.redisClient.getInstance(); if (redisClient instanceof Error) { this.logger.error('Failed to get Redis client instance', redisClient); cb(redisClient); } else { this.logger.debug('Successfully got Redis client instance, fetching queues'); redis_smq_common_1.async.waterfall([ (cb) => { this.logger.debug('Getting all queues'); (0, _get_queues_js_1._getQueues)(redisClient, cb); }, (queues, cb) => { this.logger.info(`Found ${queues.length} queues, processing each queue`); redis_smq_common_1.async.eachOf(queues, (queue, index, done) => { const queueKey = `${queue.name}@${queue.ns}`; this.logger.debug(`Processing queue ${queueKey} (${index + 1}/${queues.length})`); redis_smq_common_1.async.waterfall([ (cb) => { this.logger.debug(`Getting properties for queue ${queueKey}`); (0, _get_queue_properties_js_1._getQueueProperties)(redisClient, queue, cb); }, (properties, cb) => { this.logger.debug(`Queue ${queueKey} has delivery model ${index_js_2.EQueueDeliveryModel[properties.deliveryModel]}`); if (properties.deliveryModel === index_js_2.EQueueDeliveryModel.PUB_SUB) { this.logger.debug(`Queue ${queueKey} is PUB_SUB, getting consumer groups`); (0, _get_consumer_groups_js_1._getConsumerGroups)(redisClient, queue, (err, reply) => { if (err) { this.logger.error(`Failed to get consumer groups for queue ${queueKey}`, err); cb(err); } else { const groupCount = (reply === null || reply === void 0 ? void 0 : reply.length) || 0; this.logger.debug(`Found ${groupCount} consumer groups for queue ${queueKey}`); this.consumerGroupsByQueues[queueKey] = reply !== null && reply !== void 0 ? reply : []; cb(); } }); } else { this.logger.debug(`Queue ${queueKey} is not PUB_SUB, skipping consumer groups`); cb(); } }, ], (err) => { if (err) { this.logger.error(`Error processing queue ${queueKey}`, err); } else { this.logger.debug(`Successfully processed queue ${queueKey}`); } done(err); }); }, (err) => { if (err) { this.logger.error('Failed to process all queues', err); } else { this.logger.info('Successfully loaded consumer groups for all queues'); } cb(err); }); }, ], (err) => { if (err) { this.logger.error('Failed to load consumer groups', err); } else { this.logger.info('Consumer groups cache initialized successfully'); } cb(err); }); } }; this.cleanUpConsumerGroups = (cb) => { this.logger.debug('Cleaning up consumer groups cache'); const groupCount = Object.keys(this.consumerGroupsByQueues).length; this.consumerGroupsByQueues = {}; this.logger.info(`Cleared ${groupCount} entries from consumer groups cache`); cb(); }; this.redisClient = redisClient; this.eventBus = eventBus; this.producerId = producer.getId(); this.logger = redis_smq_common_1.logger.getLogger(index_js_1.Configuration.getSetConfig().logger, this.constructor.name.toLowerCase()); this.logger.debug(`QueueConsumerGroupsCache instance created for producer ${this.producerId}`); } getLogger() { return this.logger; } goingUp() { this.logger.debug('QueueConsumerGroupsCache is going up'); return super.goingUp().concat([this.subscribe, this.loadConsumerGroups]); } goingDown() { this.logger.debug('QueueConsumerGroupsCache is going down'); return [this.unsubscribe, this.cleanUpConsumerGroups].concat(super.goingDown()); } getConsumerGroups(queue) { const key = `${queue.name}@${queue.ns}`; this.logger.debug(`Getting consumer groups for queue ${key}`); if (this.consumerGroupsByQueues[key]) { const groupCount = this.consumerGroupsByQueues[key].length; this.logger.debug(`Found queue ${key} in cache with ${groupCount} consumer groups`); return { exists: true, consumerGroups: this.consumerGroupsByQueues[key], }; } this.logger.debug(`Queue ${key} not found in cache, returning empty result`); return { exists: false, consumerGroups: [], }; } } exports.QueueConsumerGroupsCache = QueueConsumerGroupsCache; //# sourceMappingURL=queue-consumer-groups-cache.js.map