UNPKG

redis-smq

Version:

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

172 lines 8.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FanOutExchangeManager = void 0; const types_1 = require("../../../types"); const redis_smq_common_1 = require("redis-smq-common"); const fan_out_exchange_1 = require("./fan-out-exchange"); const queue_1 = require("../queue-manager/queue"); const redis_keys_1 = require("../../common/redis-keys/redis-keys"); const configuration_1 = require("../../config/configuration"); const exchange_error_1 = require("./errors/exchange.error"); const fan_out_exchange_queue_error_1 = require("./errors/fan-out-exchange-queue.error"); class FanOutExchangeManager { constructor(config, redisClient, logger) { this.redisClient = redisClient; this.logger = logger; this.config = config; } createExchange(exchange, cb) { const { keyExchanges } = redis_keys_1.redisKeys.getMainKeys(); this.redisClient.sadd(keyExchanges, exchange.getBindingParams(), (err) => cb(err)); } deleteExchange(exchange, cb) { const { keyExchanges, keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchange.getBindingParams()); this.redisClient.watch([keyExchanges, keyExchangeBindings], (err) => { if (err) cb(err); else { this.getExchangeQueues(exchange, (err, reply = []) => { if (err) cb(err); else if (reply.length) cb(new exchange_error_1.ExchangeError(`Exchange has ${reply.length} bound queue(s). Unbind all queues before deleting the exchange.`)); else { const multi = this.redisClient.multi(); multi.srem(keyExchanges, exchange.getBindingParams()); multi.del(keyExchangeBindings); multi.exec((err) => cb(err)); } }); } }); } bindQueue(queue, exchange, cb) { const exchangeParams = exchange.getBindingParams(); const queueParams = queue_1.Queue.getParams(this.config, queue); const { keyQueues, keyQueueSettings } = redis_keys_1.redisKeys.getQueueKeys(queueParams); const { keyExchanges, keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchangeParams); redis_smq_common_1.async.waterfall([ (cb) => this.redisClient.watch([keyQueues, keyQueueSettings, keyExchangeBindings], (err) => cb(err)), (cb) => queue_1.Queue.getSettings(this.config, this.redisClient, queue, cb), (queueSettings, cb) => this.getExchangeQueues(exchange, (err, queues) => { if (err) cb(err); else { const eQueue = queues === null || queues === void 0 ? void 0 : queues.pop(); if (eQueue) queue_1.Queue.getSettings(this.config, this.redisClient, eQueue, (err, exchangeQueueSetting) => { if (err) cb(err); else if ((exchangeQueueSetting === null || exchangeQueueSetting === void 0 ? void 0 : exchangeQueueSetting.type) !== queueSettings.type) cb(new fan_out_exchange_queue_error_1.FanOutExchangeQueueError()); else cb(null, queueSettings); }); else cb(null, queueSettings); } }), (queueSettings, cb) => { const currentExchangeParams = queueSettings.exchange; if (currentExchangeParams === exchangeParams) cb(); else { const multi = this.redisClient.multi(); const queueParamsStr = JSON.stringify(queueParams); multi.sadd(keyExchanges, exchangeParams); multi.sadd(keyExchangeBindings, queueParamsStr); multi.hset(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE, exchangeParams); if (currentExchangeParams) { const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(currentExchangeParams); multi.srem(keyExchangeBindings, queueParamsStr); } multi.exec((err) => cb(err)); } }, ], (err) => { if (err) this.redisClient.unwatch(() => cb(err)); else cb(); }); } unbindQueue(queue, exchange, cb) { const exchangeName = exchange.getBindingParams(); const queueParams = queue_1.Queue.getParams(this.config, queue); const { keyQueues, keyQueueSettings } = redis_keys_1.redisKeys.getQueueKeys(queueParams); const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchangeName); redis_smq_common_1.async.waterfall([ (cb) => this.redisClient.watch([keyQueues, keyQueueSettings, keyExchangeBindings], (err) => cb(err)), (cb) => queue_1.Queue.getSettings(this.config, this.redisClient, queue, (err, settings) => { if (err) cb(err); else if ((settings === null || settings === void 0 ? void 0 : settings.exchange) !== exchangeName) cb(new exchange_error_1.ExchangeError(`Queue ${queueParams.name}@${queueParams.ns} is not bound to [${exchangeName}] exchange.`)); else cb(); }), (cb) => { const multi = this.redisClient.multi(); const queueParamsStr = JSON.stringify(queueParams); multi.srem(keyExchangeBindings, queueParamsStr); multi.hdel(keyQueueSettings, types_1.EQueueSettingType.EXCHANGE); multi.exec((err) => cb(err)); }, ], (err) => { if (err) this.redisClient.unwatch(() => cb(err)); else cb(); }); } getExchanges(cb) { const { keyExchanges } = redis_keys_1.redisKeys.getMainKeys(); this.redisClient.sscanFallback(keyExchanges, cb); } getExchangeQueues(exchange, cb) { FanOutExchangeManager.getExchangeQueues(this.redisClient, exchange, cb); } getQueueExchange(queue, cb) { FanOutExchangeManager.getQueueExchange(this.config, this.redisClient, queue, cb); } quit(cb) { this.redisClient.halt(cb); } static getExchangeQueues(redisClient, exchange, cb) { const { keyExchangeBindings } = redis_keys_1.redisKeys.getFanOutExchangeKeys(exchange.getBindingParams()); redisClient.sscanFallback(keyExchangeBindings, (err, reply) => { if (err) cb(err); else { const queues = (reply !== null && reply !== void 0 ? reply : []).map((i) => JSON.parse(i)); cb(null, queues); } }); } static getQueueExchange(config, redisClient, queue, cb) { queue_1.Queue.getSettings(config, redisClient, queue, (err, reply) => { if (err) cb(err); else cb(null, (reply === null || reply === void 0 ? void 0 : reply.exchange) ? new fan_out_exchange_1.FanOutExchange(reply.exchange) : null); }); } static createInstance(config = {}, cb) { const cfg = (0, configuration_1.getConfiguration)(config); const redis = cfg.redis; (0, redis_smq_common_1.createClientInstance)(redis, (err, client) => { if (err) cb(err); else if (!client) cb(new redis_smq_common_1.errors.EmptyCallbackReplyError()); else { const loggerCfg = cfg.logger; const nsLogger = redis_smq_common_1.logger.getNamespacedLogger(loggerCfg, 'queue-manager'); const fanOutExchangeManager = new FanOutExchangeManager(cfg, client, nsLogger); cb(null, fanOutExchangeManager); } }); } } exports.FanOutExchangeManager = FanOutExchangeManager; //# sourceMappingURL=fan-out-exchange-manager.js.map