UNPKG

redis-smq

Version:

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

205 lines 9.95 kB
import { async, CallbackEmptyReplyError, createLogger, } from 'redis-smq-common'; import { redisKeys } from '../common/redis/redis-keys/redis-keys.js'; import { Configuration } from '../config-manager/configuration.js'; import { _deleteQueue } from '../queue-manager/_/_delete-queue.js'; import { InvalidNamespaceError, NamespaceNotFoundError, QueueNotFoundError, } from '../errors/index.js'; import { withSharedPoolConnection } from '../common/redis/redis-connection-pool/with-shared-pool-connection.js'; import { _getNamespaceQueues } from './_/_get-namespace-queues.js'; import { validateRedisKey } from '../common/redis/redis-keys/validator.js'; export class NamespaceManager { logger; constructor() { this.logger = createLogger(Configuration.getConfig().logger, this.constructor.name.toLowerCase()); } getNamespaces(cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting all namespaces'); withSharedPoolConnection((client, cb) => { const { keyNamespaces } = redisKeys.getMainKeys(); this.logger.debug('Fetching namespaces from Redis', { key: keyNamespaces, }); client.smembers(keyNamespaces, (err, reply) => { if (err) { this.logger.error('Failed to get namespaces', { error: err.message, }); return cb(err); } if (!reply) { this.logger.error('Empty namespaces reply'); return cb(new CallbackEmptyReplyError()); } this.logger.debug('Successfully retrieved namespaces', { count: reply.length, }); cb(null, reply); }); }, callback); }); } getNamespaceQueues(namespace, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Getting queues for namespace', { namespace }); const ns = validateRedisKey(namespace); if (ns instanceof Error) { this.logger.error('Invalid namespace', { namespace }); return callback(new InvalidNamespaceError()); } withSharedPoolConnection((client, cb) => { const { keyNamespaces } = redisKeys.getMainKeys(); const { keyNamespaceQueues } = redisKeys.getNamespaceKeys(ns); this.logger.debug('Checking if namespace exists', { namespace: ns, key: keyNamespaces, }); async.waterfall([ (cb) => { client.sismember(keyNamespaces, ns, (err, reply) => { if (err) { this.logger.error('Failed to check namespace existence', { namespace: ns, error: err.message, }); return cb(err); } if (!reply) { this.logger.error('Namespace not found', { namespace: ns, }); return cb(new NamespaceNotFoundError()); } this.logger.debug('Namespace exists', { namespace: ns }); cb(); }); }, (_, cb) => { this.logger.debug('Fetching queues for namespace', { namespace: ns, key: keyNamespaceQueues, }); client.smembers(keyNamespaceQueues, (err, reply) => { if (err) { this.logger.error('Failed to get namespace queues', { namespace: ns, error: err.message, }); return cb(err); } if (!reply) { this.logger.error('Empty queues reply', { namespace: ns }); return cb(new CallbackEmptyReplyError()); } const messageQueues = reply.map((i) => JSON.parse(i)); this.logger.debug('Successfully retrieved namespace queues', { namespace: ns, queueCount: messageQueues.length, }); cb(null, messageQueues); }); }, ], cb); }, callback); }); } delete(namespace, cb) { return async.withOptionalCallback(cb, (callback) => { this.logger.debug('Deleting namespace', { namespace }); const ns = validateRedisKey(namespace); if (ns instanceof Error) { this.logger.error('Invalid namespace', { namespace }); return callback(new InvalidNamespaceError()); } withSharedPoolConnection((client, cb) => { const { keyNamespaces } = redisKeys.getMainKeys(); this.logger.debug('Checking if namespace exists before deletion', { namespace: ns, key: keyNamespaces, }); async.waterfall([ (cb) => { client.sismember(keyNamespaces, ns, (err, isMember) => { if (err) { this.logger.error('Failed to check namespace existence', { namespace: ns, error: err.message, }); return cb(err); } if (!isMember) { this.logger.error('Namespace not found for deletion', { namespace: ns, }); return cb(new NamespaceNotFoundError()); } this.logger.debug('Namespace exists, proceeding with deletion', { namespace: ns, }); cb(); }); }, (_, cb) => { this.logger.debug('Getting all queues for deletion', { namespace: ns, }); _getNamespaceQueues(client, ns, (err, reply) => { if (err) { this.logger.error('Failed to get namespace queues for deletion', { namespace: ns, error: err.message, }); } cb(err, reply); }); }, (queues, cb) => { this.logger.debug('Preparing to delete namespace and its queues', { namespace: ns, queueCount: queues.length, }); async.eachOf(queues, (queueParams, _, done) => { this.logger.debug('Deleting queue', { namespace: ns, queue: queueParams.name, }); _deleteQueue(client, queueParams, (err) => { if (err) { this.logger.error('Failed to delete queue', { namespace: ns, queue: queueParams.name, error: err, }); if (err instanceof QueueNotFoundError) return done(); } done(err); }); }, (err) => { if (err) { this.logger.error('Failed during queue deletion', { namespace: ns, error: err, }); return cb(err); } client.srem(keyNamespaces, ns, (err) => { if (err) { this.logger.error('Failed to delete namespace', { namespace: ns, error: err, }); return cb(err); } this.logger.debug('Successfully deleted namespace', { namespace: ns, }); cb(); }); }); }, ], (err) => cb(err)); }, callback); }); } } //# sourceMappingURL=namespace-manager.js.map