redis-smq
Version:
A simple high-performance Redis message queue for Node.js.
172 lines • 8.39 kB
JavaScript
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
;