UNPKG

redis-smq

Version:

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

259 lines 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueManager = void 0; const redis_smq_common_1 = require("redis-smq-common"); const scripts_js_1 = require("../common/redis/scripts.js"); const redis_keys_js_1 = require("../common/redis/redis-keys/redis-keys.js"); const configuration_js_1 = require("../config-manager/configuration.js"); const _delete_queue_js_1 = require("./_/_delete-queue.js"); const _get_queue_consumer_ids_js_1 = require("./_/_get-queue-consumer-ids.js"); const _get_queue_consumers_js_1 = require("./_/_get-queue-consumers.js"); const _get_queue_properties_js_1 = require("./_/_get-queue-properties.js"); const _get_queues_js_1 = require("./_/_get-queues.js"); const _parse_queue_params_js_1 = require("./_/_parse-queue-params.js"); const _queue_exists_js_1 = require("./_/_queue-exists.js"); const index_js_1 = require("../errors/index.js"); const index_js_2 = require("./types/index.js"); const with_shared_pool_connection_js_1 = require("../common/redis/redis-connection-pool/with-shared-pool-connection.js"); const event_multiplexer_js_1 = require("../event-bus/event-multiplexer.js"); const _set_queue_state_js_1 = require("../queue-state-manager/_/_set-queue-state.js"); const index_js_3 = require("../queue-state-manager/index.js"); class QueueManager { constructor() { const config = configuration_js_1.Configuration.getConfig(); this.logger = (0, redis_smq_common_1.createLogger)(config.logger, this.constructor.name); } save(queue, queueType, deliveryModel, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Saving queue: ${queueDesc}, type: ${queueType}, delivery model: ${deliveryModel}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); return callback(queueParams); } const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, done) => { const { keyQueueProperties, keyQueueStateHistory } = redis_keys_js_1.redisKeys.getQueueKeys(queueParams.ns, queueParams.name, null); const { keyNamespaces, keyQueues } = redis_keys_js_1.redisKeys.getMainKeys(); const { keyNamespaceQueues } = redis_keys_js_1.redisKeys.getNamespaceKeys(queueParams.ns); const keys = [ keyNamespaces, keyNamespaceQueues, keyQueues, keyQueueProperties, keyQueueStateHistory, ]; const now = Date.now(); const initialState = { timestamp: now, from: null, to: index_js_2.EQueueOperationalState.ACTIVE, reason: index_js_3.ESystemStateTransitionReason.SYSTEM_INIT, metadata: { queueType, deliveryModel, }, }; const initialTransitionData = JSON.stringify(initialState); const args = [ queueParams.ns, JSON.stringify(queueParams), index_js_2.EQueueProperty.QUEUE_TYPE, queueType, index_js_2.EQueueProperty.DELIVERY_MODEL, deliveryModel, index_js_2.EQueueProperty.RATE_LIMIT, '', index_js_2.EQueueProperty.MESSAGES_COUNT, index_js_2.EQueueProperty.ACKNOWLEDGED_MESSAGES_COUNT, index_js_2.EQueueProperty.DEAD_LETTERED_MESSAGES_COUNT, index_js_2.EQueueProperty.PENDING_MESSAGES_COUNT, index_js_2.EQueueProperty.SCHEDULED_MESSAGES_COUNT, index_js_2.EQueueProperty.PROCESSING_MESSAGES_COUNT, index_js_2.EQueueProperty.DELAYED_MESSAGES_COUNT, index_js_2.EQueueProperty.REQUEUED_MESSAGES_COUNT, index_js_2.EQueueProperty.OPERATIONAL_STATE, index_js_2.EQueueOperationalState.ACTIVE, _set_queue_state_js_1.maxQueueStateHistorySize, index_js_2.EQueueProperty.LAST_STATE_CHANGE_AT, now, index_js_2.EQueueProperty.LOCK_ID, initialTransitionData, ]; this.logger.debug(`Executing CREATE_QUEUE script for ${queueName} with keys: [${keys.join(', ')}]`); client.runScript(scripts_js_1.ERedisScriptName.CREATE_QUEUE, keys, args, (err, reply) => { if (err) return done(err); if (!['OK', 'QUEUE_EXISTS'].includes(String(reply))) { this.logger.error('CREATE_QUEUE script returned an unexpected reply: ', reply); return done(new index_js_1.UnexpectedScriptReplyError({ metadata: { reply } })); } if (reply === 'QUEUE_EXISTS') { const error = new index_js_1.QueueAlreadyExistsError(); this.logger.error(`Queue ${queueName} already exists`, error); return done(error); } this.logger.debug(`Queue ${queueName} created successfully.`); const properties = { queueType, deliveryModel, rateLimit: null, messagesCount: 0, acknowledgedMessagesCount: 0, deadLetteredMessagesCount: 0, pendingMessagesCount: 0, scheduledMessagesCount: 0, processingMessagesCount: 0, delayedMessagesCount: 0, requeuedMessagesCount: 0, operationalState: index_js_2.EQueueOperationalState.ACTIVE, lockId: null, lastStateChangeAt: now, }; this.logger.debug(`Emitting queue.queueCreated event for ${queueName}`); event_multiplexer_js_1.EventMultiplexer.publish('queue.queueCreated', queueParams, properties); this.logger.info(`Queue ${queueName} successfully created with type=${queueType}, deliveryModel=${deliveryModel}, state=${index_js_2.EQueueOperationalState.ACTIVE}`); done(null, { queue: queueParams, properties }); }); }, callback); }); } exists(queue, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Checking if queue exists: ${queueDesc}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); callback(queueParams); } else { const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => { this.logger.debug(`Checking if queue ${queueName} exists in Redis`); (0, _queue_exists_js_1._queueExists)(client, queueParams, (err, exists) => { if (err) { this.logger.error(`Error checking if queue ${queueName} exists: ${err.message}`, err); cb(err); } else { this.logger.debug(`Queue ${queueName} exists: ${exists}`); cb(null, exists); } }); }, callback); } }); } delete(queue, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Deleting queue: ${queueDesc}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); return callback(queueParams); } const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => { this.logger.debug(`Executing delete queue operation for ${queueName}`); (0, _delete_queue_js_1._deleteQueue)(client, queueParams, (err) => { if (err) { this.logger.error(`Error deleting queue ${queueName}: ${err.message}`, err); return cb(err); } this.logger.debug(`Queue ${queueName} deleted from Redis, emitting queue.queueDeleted event`); event_multiplexer_js_1.EventMultiplexer.publish('queue.queueDeleted', queueParams); this.logger.info(`Queue ${queueParams.name}@${queueParams.ns} successfully deleted`); cb(); }); }, callback); }); } getProperties(queue, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Getting properties for queue: ${queueDesc}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); callback(queueParams); } else { const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => { this.logger.debug(`Retrieving properties for queue ${queueName}`); (0, _get_queue_properties_js_1._getQueueProperties)(client, queueParams, (err, properties) => { if (err) { this.logger.error(`Error getting properties for queue ${queueName}: ${err.message}`, err); cb(err); } else { if (properties) { this.logger.debug(`Retrieved properties for queue ${queueName}: type=${index_js_2.EQueueType[properties.queueType]}, deliveryModel=${index_js_2.EQueueDeliveryModel[properties.deliveryModel]}, state=${properties.operationalState}`); } else { this.logger.debug(`No properties found for queue ${queueName}`); } cb(null, properties); } }); }, callback); } }); } getQueues(cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting all queues'); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => { this.logger.debug('Retrieving all queues from Redis'); (0, _get_queues_js_1._getQueues)(client, (err, queues) => { if (err) { this.logger.error(`Error getting queues: ${err.message}`, err); cb(err); } else { const queueCount = (queues === null || queues === void 0 ? void 0 : queues.length) || 0; this.logger.debug(`Retrieved ${queueCount} queues`); cb(null, queues); } }); }, callback); }); } getConsumers(queue, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Getting consumers for queue: ${queueDesc}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); return callback(queueParams); } const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => (0, _get_queue_consumers_js_1._getQueueConsumers)(client, queueParams, cb), callback); }); } getConsumerIds(queue, cb) { return redis_smq_common_1.async.withOptionalCallback(cb, (callback) => { const queueDesc = typeof queue === 'string' ? queue : `${queue.name}@${queue.ns}`; this.logger.debug(`Getting consumer Ids for queue: ${queueDesc}`); const queueParams = (0, _parse_queue_params_js_1._parseQueueParams)(queue); if (queueParams instanceof Error) { this.logger.error(`Error parsing queue parameters for ${queueDesc}: ${queueParams.message}`, queueParams); return callback(queueParams); } const queueName = `${queueParams.name}@${queueParams.ns}`; this.logger.debug(`Parsed queue parameters: ${queueName}`); (0, with_shared_pool_connection_js_1.withSharedPoolConnection)((client, cb) => (0, _get_queue_consumer_ids_js_1._getQueueConsumerIds)(client, queueParams, cb), callback); }); } } exports.QueueManager = QueueManager; //# sourceMappingURL=queue-manager.js.map