UNPKG

redis-smq

Version:

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

168 lines 8.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PubSubTargetResolver = void 0; const redis_smq_common_1 = require("redis-smq-common"); const _get_consumer_groups_js_1 = require("../consumer-groups/_/_get-consumer-groups.js"); const _get_queue_properties_js_1 = require("../queue-manager/_/_get-queue-properties.js"); const _get_queues_js_1 = require("../queue-manager/_/_get-queues.js"); const index_js_1 = require("../queue-manager/index.js"); const with_shared_pool_connection_js_1 = require("../common/redis/redis-connection-pool/with-shared-pool-connection.js"); const internal_event_bus_js_1 = require("../event-bus/internal-event-bus.js"); class PubSubTargetResolver extends redis_smq_common_1.Runnable { constructor(producer, logger) { super(); this.pubSubTargets = {}; this.onConsumerGroupCreated = (queue, groupId) => { const queueKey = this.getQueueKey(queue); this.logger.debug(`Handling 'consumerGroupCreated' event for group [${groupId}] on queue [${queueKey}]`); if (this.pubSubTargets[queueKey]) { const targets = this.pubSubTargets[queueKey]; if (!targets.includes(groupId)) { targets.push(groupId); this.logger.debug(`Added group [${groupId}] to cache for queue [${queueKey}].`); } } }; this.onConsumerGroupDeleted = (queue, groupId) => { const queueKey = this.getQueueKey(queue); this.logger.debug(`Handling 'consumerGroupDeleted' event for group [${groupId}] on queue [${queueKey}]`); if (this.pubSubTargets[queueKey]) { const targets = this.pubSubTargets[queueKey]; const index = targets.indexOf(groupId); if (index > -1) { targets.splice(index, 1); this.logger.debug(`Removed group [${groupId}] from cache for queue [${queueKey}].`); } } }; this.onQueueCreated = (queue, properties) => { var _a; const queueKey = this.getQueueKey(queue); this.logger.debug(`Handling 'queueCreated' event for queue [${queueKey}] with delivery model [${index_js_1.EQueueDeliveryModel[properties.deliveryModel]}]`); if (properties.deliveryModel === index_js_1.EQueueDeliveryModel.PUB_SUB) { this.pubSubTargets[queueKey] = (_a = this.pubSubTargets[queueKey]) !== null && _a !== void 0 ? _a : []; this.logger.debug(`Added PUB/SUB queue [${queueKey}] to cache.`); } }; this.onQueueDeleted = (queue) => { const queueKey = this.getQueueKey(queue); this.logger.debug(`Handling 'queueDeleted' event for queue [${queueKey}]`); if (this.pubSubTargets[queueKey]) { delete this.pubSubTargets[queueKey]; this.logger.debug(`Removed queue [${queueKey}] from cache.`); } }; this.subscribeToEvents = (cb) => { this.logger.debug('Subscribing to queue and consumer group events...'); this.internalEventBus.on('queue.queueCreated', this.onQueueCreated); this.internalEventBus.on('queue.queueDeleted', this.onQueueDeleted); this.internalEventBus.on('queue.consumerGroupCreated', this.onConsumerGroupCreated); this.internalEventBus.on('queue.consumerGroupDeleted', this.onConsumerGroupDeleted); this.logger.debug('Successfully subscribed to events.'); cb(); }; this.unsubscribeFromEvents = (cb) => { this.logger.debug('Unsubscribing from events...'); this.internalEventBus.removeListener('queue.queueCreated', this.onQueueCreated); this.internalEventBus.removeListener('queue.queueDeleted', this.onQueueDeleted); this.internalEventBus.removeListener('queue.consumerGroupCreated', this.onConsumerGroupCreated); this.internalEventBus.removeListener('queue.consumerGroupDeleted', this.onConsumerGroupDeleted); this.logger.debug('Successfully unsubscribed from all events.'); cb(); }; this.loadAndCacheInitialTargets = (cb) => { this.logger.debug('Loading and caching initial PUB/SUB targets...'); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((redisClient, cb) => { redis_smq_common_1.async.waterfall([ (cb) => { (0, _get_queues_js_1._getQueues)(redisClient, cb); }, (queues, cb) => { this.logger.debug(`Found [${queues.length}] queues to process.`); redis_smq_common_1.async.eachOf(queues, (queue, index, done) => { const queueKey = this.getQueueKey(queue); this.logger.debug(`Processing queue [${queueKey}] (${index + 1}/${queues.length})`); redis_smq_common_1.async.waterfall([ (cb) => { (0, _get_queue_properties_js_1._getQueueProperties)(redisClient, queue, cb); }, (properties, cb) => { if (properties.deliveryModel === index_js_1.EQueueDeliveryModel.PUB_SUB) { (0, _get_consumer_groups_js_1._getConsumerGroups)(redisClient, queue, (err, reply) => { if (err) return cb(err); const targets = reply !== null && reply !== void 0 ? reply : []; this.pubSubTargets[queueKey] = targets; this.logger.debug(`Cached [${targets.length}] targets for PUB/SUB queue [${queueKey}].`); cb(); }); } else { cb(); } }, ], (err) => { if (err) { this.logger.error(`Error processing queue [${queueKey}]. Skipping.`, err); } done(); }); }, () => { this.logger.debug('Finished initial loading of PUB/SUB targets.'); cb(); }); }, ], (err) => { if (err) { this.logger.error('Failed to complete initial target loading.', err); } else { this.logger.debug('Initial target cache is ready.'); } cb(err); }); }, cb); }; this.clearCache = (cb) => { this.logger.debug('Clearing PUB/SUB target cache...'); const count = Object.keys(this.pubSubTargets).length; this.pubSubTargets = {}; this.logger.debug(`Cleared [${count}] entries from cache.`); cb(); }; this.producerId = producer.getId(); this.logger = logger.createLogger(this.constructor.name); this.internalEventBus = internal_event_bus_js_1.InternalEventBus.getInstance(); this.logger.debug(`PubSubTargetResolver instance created for producer ${this.producerId}`); } getQueueKey(queue) { return `${queue.name}@${queue.ns}`; } goingUp() { return super .goingUp() .concat([this.subscribeToEvents, this.loadAndCacheInitialTargets]); } goingDown() { return [this.unsubscribeFromEvents, this.clearCache].concat(super.goingDown()); } resolveTargets(queue) { const queueKey = this.getQueueKey(queue); this.logger.debug(`Resolving targets for queue [${queueKey}]`); if (this.pubSubTargets[queueKey]) { const targets = this.pubSubTargets[queueKey]; this.logger.debug(`Found queue [${queueKey}] in cache with [${targets.length}] targets.`); return { isPubSub: true, targets, }; } this.logger.debug(`Queue [${queueKey}] not found in cache.`); return { isPubSub: false, targets: [], }; } } exports.PubSubTargetResolver = PubSubTargetResolver; //# sourceMappingURL=pub-sub-target-resolver.js.map