UNPKG

redis-smq

Version:

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

157 lines 7.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DequeueMessage = void 0; const redis_smq_common_1 = require("redis-smq-common"); const redis_keys_js_1 = require("../../../common/redis/redis-keys/redis-keys.js"); const _has_rate_limit_exceeded_js_1 = require("../../../queue-rate-limit/_/_has-rate-limit-exceeded.js"); const _get_queue_properties_js_1 = require("../../../queue-manager/_/_get-queue-properties.js"); const index_js_1 = require("../../../index.js"); const event_publisher_js_1 = require("./event-publisher.js"); const connection_pool_js_1 = require("../../../common/redis/redis-connection-pool/types/connection-pool.js"); const redis_connection_pool_js_1 = require("../../../common/redis/redis-connection-pool/redis-connection-pool.js"); class DequeueMessage extends redis_smq_common_1.Runnable { constructor(consumerContext, queue, blockUntilMessageReceived = true, autoCloseRedisConnection = true) { super(); this.redisClient = null; this.queueRateLimit = null; this.queueType = null; this.handleMessage = (err, messageId) => { if (err) { this.handleError(err); } else if (typeof messageId === 'string') { this.emit('consumer.dequeueMessage.messageReceived', messageId, this.queue, this.consumerContext.consumerId); } else { this.emit('consumer.dequeueMessage.nextMessage'); } }; this.consumerContext = consumerContext; this.logger = consumerContext.logger.createLogger(this.constructor.name); this.config = consumerContext.config; this.queue = queue; this.blockUntilMessageReceived = blockUntilMessageReceived; this.autoCloseRedisConnection = autoCloseRedisConnection; (0, event_publisher_js_1.eventPublisher)(this); const { keyConsumerQueues } = redis_keys_js_1.redisKeys.getConsumerKeys(this.consumerContext.consumerId); const { keyQueueProcessing } = redis_keys_js_1.redisKeys.getQueueConsumerKeys(this.queue.queueParams, this.consumerContext.consumerId); const { keyQueues } = redis_keys_js_1.redisKeys.getMainKeys(); const { keyQueueProcessingQueues, keyQueuePending, keyQueuePriority, keyQueueConsumers, keyQueueProperties, } = redis_keys_js_1.redisKeys.getQueueKeys(this.queue.queueParams.ns, this.queue.queueParams.name, this.queue.groupId); this.keyQueueProperties = keyQueueProperties; this.keyQueuePriorityPending = keyQueuePriority; this.keyQueuePending = keyQueuePending; this.keyQueueProcessing = keyQueueProcessing; this.keyQueues = keyQueues; this.keyQueueConsumers = keyQueueConsumers; this.keyConsumerQueues = keyConsumerQueues; this.keyQueueProcessingQueues = keyQueueProcessingQueues; } runDequeue(redisClient) { if (this.queueRateLimit) { (0, _has_rate_limit_exceeded_js_1._hasRateLimitExceeded)(redisClient, this.queue.queueParams, this.queueRateLimit, (err, isExceeded) => { if (err) this.handleError(err); else if (isExceeded) { this.emit('consumer.dequeueMessage.nextMessage'); } else { this.performDequeue(redisClient); } }); } else { this.performDequeue(redisClient); } } performDequeue(redisClient) { if (this.isPriorityQueuingEnabled()) { redisClient.zpoplpush(this.keyQueuePriorityPending, this.keyQueueProcessing, this.handleMessage); } else if (this.blockUntilMessageReceived && !this.queueRateLimit) { redisClient.brpoplpush(this.keyQueuePending, this.keyQueueProcessing, 0, this.handleMessage); } else { redisClient.rpoplpush(this.keyQueuePending, this.keyQueueProcessing, this.handleMessage); } } getRedisClient() { if (!this.redisClient) return new redis_smq_common_1.PanicError({ message: 'A RedisClient instance is required.' }); return this.redisClient; } handleError(err) { if (!this.isOperational()) return; this.logger.error(`DequeueMessage error: ${err.message}`, err); this.emit('consumer.dequeueMessage.error', err, this.consumerContext.consumerId, this.queue); super.handleError(err); } goingUp() { return super.goingUp().concat([ (cb) => { const redisConnectionAcquisitionMode = this.blockUntilMessageReceived ? connection_pool_js_1.ERedisConnectionAcquisitionMode.EXCLUSIVE : connection_pool_js_1.ERedisConnectionAcquisitionMode.SHARED; redis_connection_pool_js_1.RedisConnectionPool.getInstance().acquire(redisConnectionAcquisitionMode, (err, redisClient) => { if (err) return cb(err); if (!redisClient) return cb(new redis_smq_common_1.CallbackEmptyReplyError()); this.redisClient = redisClient; cb(); }); }, (cb) => { const redisClient = this.getRedisClient(); if (redisClient instanceof Error) return cb(redisClient); (0, _get_queue_properties_js_1._getQueueProperties)(redisClient, this.queue.queueParams, (err, queueProperties) => { var _a; if (err) return cb(err); if (!queueProperties) return cb(new redis_smq_common_1.CallbackEmptyReplyError()); this.queueType = queueProperties.queueType; this.queueRateLimit = (_a = queueProperties.rateLimit) !== null && _a !== void 0 ? _a : null; cb(); }); }, ]); } goingDown() { return [ (cb) => { if (this.redisClient) { if (this.autoCloseRedisConnection) { redis_connection_pool_js_1.RedisConnectionPool.getInstance().destroy(this.redisClient, () => { this.redisClient = null; cb(); }); } else { redis_connection_pool_js_1.RedisConnectionPool.getInstance().release(this.redisClient); this.redisClient = null; cb(); } } else cb(); }, ].concat(super.goingDown()); } isPriorityQueuingEnabled() { return this.queueType === index_js_1.EQueueType.PRIORITY_QUEUE; } dequeue() { if (!this.isOperational()) { return; } const redisClient = this.getRedisClient(); if (redisClient instanceof Error) { return this.handleError(redisClient); } this.runDequeue(redisClient); } } exports.DequeueMessage = DequeueMessage; //# sourceMappingURL=dequeue-message.js.map