UNPKG

redis-smq

Version:

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

216 lines 10.2 kB
import { async, CallbackEmptyReplyError } from 'redis-smq-common'; import { redisKeys } from '../../../common/redis-keys/redis-keys.js'; import { _getQueueProperties } from '../../queue/_/_get-queue-properties.js'; import { _parseQueueParams } from '../../queue/_/_parse-queue-params.js'; import { EQueueProperty, } from '../../queue/index.js'; import { ExchangeFanOutExchangeHasBoundQueuesError, ExchangeFanOutQueueTypeError, ExchangeQueueIsNotBoundToExchangeError, } from '../errors/index.js'; import { ExchangeAbstract } from '../exchange-abstract.js'; import { _getFanOutExchangeQueues } from './_/_get-fan-out-exchange-queues.js'; import { _getQueueFanOutExchange } from './_/_get-queue-fan-out-exchange.js'; import { _validateExchangeFanOutParams } from './_/_validate-exchange-fan-out-params.js'; export class ExchangeFanOut extends ExchangeAbstract { getQueues(exchangeParams, cb) { const fanOutName = _validateExchangeFanOutParams(exchangeParams); if (fanOutName instanceof Error) cb(fanOutName); else { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _getFanOutExchangeQueues(client, fanOutName, cb); }); } } saveExchange(exchangeParams, cb) { const fanOutName = _validateExchangeFanOutParams(exchangeParams); if (fanOutName instanceof Error) cb(fanOutName); else { const { keyFanOutExchanges } = redisKeys.getMainKeys(); this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else { client?.sadd(keyFanOutExchanges, fanOutName, (err) => cb(err)); } }); } } deleteExchange(exchangeParams, cb) { const fanOutName = _validateExchangeFanOutParams(exchangeParams); if (fanOutName instanceof Error) cb(fanOutName); else { const { keyExchangeBindings } = redisKeys.getFanOutExchangeKeys(fanOutName); const { keyFanOutExchanges } = redisKeys.getMainKeys(); this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else { client?.watch([keyFanOutExchanges, keyExchangeBindings], (err) => { if (err) cb(err); else { _getFanOutExchangeQueues(client, fanOutName, (err, reply = []) => { if (err) cb(err); else if (reply.length) cb(new ExchangeFanOutExchangeHasBoundQueuesError()); else { const multi = client.multi(); multi.srem(keyFanOutExchanges, fanOutName); multi.del(keyExchangeBindings); multi.exec((err) => cb(err)); } }); } }); } }); } } bindQueue(queue, exchangeParams, cb) { const queueParams = _parseQueueParams(queue); const fanOutName = _validateExchangeFanOutParams(exchangeParams); if (queueParams instanceof Error) cb(queueParams); else if (fanOutName instanceof Error) cb(fanOutName); else { const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null); const { keyExchangeBindings } = redisKeys.getFanOutExchangeKeys(fanOutName); const { keyQueues, keyFanOutExchanges } = redisKeys.getMainKeys(); this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else { async.waterfall([ (cb) => client.watch([keyQueues, keyQueueProperties, keyExchangeBindings], (err) => cb(err)), (cb) => _getQueueProperties(client, queueParams, cb), (queueProperties, cb) => _getFanOutExchangeQueues(client, fanOutName, (err, queues) => { if (err) cb(err); else { const eQueue = queues?.pop(); if (eQueue) _getQueueProperties(client, eQueue, (err, exchangeQueueProperties) => { if (err) cb(err); else if (!exchangeQueueProperties) cb(new CallbackEmptyReplyError()); else if (exchangeQueueProperties.queueType !== queueProperties.queueType) cb(new ExchangeFanOutQueueTypeError()); else cb(null, queueProperties); }); else cb(null, queueProperties); } }), (queueProperties, cb) => { const currentExchangeParams = queueProperties.exchange; if (currentExchangeParams === fanOutName) cb(); else { const multi = client.multi(); const queueParamsStr = JSON.stringify(queueParams); multi.sadd(keyFanOutExchanges, fanOutName); multi.sadd(keyExchangeBindings, queueParamsStr); multi.hset(keyQueueProperties, String(EQueueProperty.EXCHANGE), fanOutName); if (currentExchangeParams) { const { keyExchangeBindings } = redisKeys.getFanOutExchangeKeys(currentExchangeParams); multi.srem(keyExchangeBindings, queueParamsStr); } multi.exec((err) => cb(err)); } }, ], (err) => { if (err) client.unwatch(() => cb(err)); else cb(); }); } }); } } unbindQueue(queue, exchangeParams, cb) { const queueParams = _parseQueueParams(queue); const fanOutName = _validateExchangeFanOutParams(exchangeParams); if (queueParams instanceof Error) cb(queueParams); else if (fanOutName instanceof Error) cb(fanOutName); else { const { keyQueueProperties } = redisKeys.getQueueKeys(queueParams, null); const { keyQueues } = redisKeys.getMainKeys(); const { keyExchangeBindings } = redisKeys.getFanOutExchangeKeys(fanOutName); this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else { async.waterfall([ (cb) => client.watch([keyQueues, keyQueueProperties, keyExchangeBindings], (err) => cb(err)), (cb) => _getQueueProperties(client, queueParams, (err, properties) => { if (err) cb(err); else if (!properties) cb(new CallbackEmptyReplyError()); else if (properties.exchange !== fanOutName) cb(new ExchangeQueueIsNotBoundToExchangeError()); else cb(); }), (cb) => { const multi = client.multi(); const queueParamsStr = JSON.stringify(queueParams); multi.srem(keyExchangeBindings, queueParamsStr); multi.hdel(keyQueueProperties, String(EQueueProperty.EXCHANGE)); multi.exec((err) => cb(err)); }, ], (err) => { if (err) client.unwatch(() => cb(err)); else cb(); }); } }); } } getAllExchanges(cb) { const { keyFanOutExchanges } = redisKeys.getMainKeys(); this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else client.sscanAll(keyFanOutExchanges, {}, cb); }); } getQueueExchange(queue, cb) { const queueParams = _parseQueueParams(queue); if (queueParams instanceof Error) cb(queueParams); else { this.redisClient.getSetInstance((err, client) => { if (err) cb(err); else if (!client) cb(new CallbackEmptyReplyError()); else _getQueueFanOutExchange(client, queueParams, cb); }); } } } //# sourceMappingURL=exchange-fan-out.js.map