UNPKG

redis-smq

Version:

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

186 lines 8.27 kB
import { EQueueOperationalState, } from '../../queue-manager/index.js'; import { InternalEventBus } from '../../event-bus/internal-event-bus.js'; export class QueueStateChangeHandler { messageHandlerRunner; internalEventBus; logger; pausedQueues = new Map(); stoppedQueues = new Map(); lockedQueues = new Map(); constructor(messageHandlerRunner, logger) { this.messageHandlerRunner = messageHandlerRunner; this.logger = logger.createLogger(this.constructor.name); this.internalEventBus = InternalEventBus.getInstance(); this.internalEventBus.on('queue.stateChanged', this.onQueueStateChange); this.logger.debug('QueueStateChangeHandler initialized'); } onQueueStateChange = (queue, transition) => { const queueKey = this.getQueueKey(queue); const fromState = transition.from; const toState = transition.to; this.logger.info(`Queue state changed: ${queueKey} from ${fromState} to ${toState}`); this.stoppedQueues.delete(queueKey); this.pausedQueues.delete(queueKey); this.lockedQueues.delete(queueKey); switch (toState) { case EQueueOperationalState.STOPPED: this.stoppedQueues.set(queueKey, queue); this.handleQueueStopped(queue); break; case EQueueOperationalState.PAUSED: this.pausedQueues.set(queueKey, queue); this.handleQueuePaused(queue); break; case EQueueOperationalState.LOCKED: this.lockedQueues.set(queueKey, queue); this.handleQueueLocked(queue); break; case EQueueOperationalState.ACTIVE: this.handleQueueActive(queue); break; default: this.logger.warn(`Unknown queue state: ${toState} for queue: ${queueKey}`); } }; handleQueueStopped(queue) { this.logger.debug(`Handling STOPPED state for queue: ${queue.name}`); const queueConfigs = this.getQueueConfigurationsForQueue(queue); if (queueConfigs.length === 0) { this.logger.debug(`No queue configurations found for queue: ${queue.name}`); return; } this.stopAllQueueHandlers(queueConfigs, 'STOPPED'); } handleQueuePaused(queue) { this.logger.debug(`Handling PAUSED state for queue: ${queue.name}`); const queueConfigs = this.getQueueConfigurationsForQueue(queue); if (queueConfigs.length === 0) { this.logger.debug(`No queue configurations found for queue: ${queue.name}`); return; } this.stopAllQueueHandlers(queueConfigs, 'PAUSED'); } handleQueueLocked(queue) { this.logger.debug(`Handling LOCKED state for queue: ${queue.name}`); const queueConfigs = this.getQueueConfigurationsForQueue(queue); if (queueConfigs.length === 0) { this.logger.debug(`No queue configurations found for queue: ${queue.name}`); return; } this.stopAllQueueHandlers(queueConfigs, 'LOCKED'); } handleQueueActive(queue) { this.logger.debug(`Handling ACTIVE state for queue: ${queue.name}`); const queueConfigs = this.getQueueConfigurationsForQueue(queue); if (queueConfigs.length === 0) { this.logger.debug(`No queue configurations found for queue: ${queue.name}`); return; } this.startAllQueueHandlers(queueConfigs); } getQueueConfigurationsForQueue(queue) { const allQueues = this.messageHandlerRunner.getQueues(); return allQueues.filter((q) => q.queueParams.ns === queue.ns && q.queueParams.name === queue.name); } stopAllQueueHandlers(queueConfigs, state) { let stoppedCount = 0; const totalCount = queueConfigs.length; const checkCompletion = () => { if (stoppedCount === totalCount) { this.logger.debug(`All ${totalCount} handler(s) for queue ${queueConfigs[0].queueParams.name} have been ${state.toLowerCase()}`); } }; queueConfigs.forEach((queueParsed) => { this.messageHandlerRunner.stopMessageHandler(queueParsed, (err, wasRunning) => { if (err) { this.logger.error(`Failed to ${state.toLowerCase()} message handler for queue ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'}):`, err); } else { if (wasRunning) { this.logger.debug(`Message handler ${state.toLowerCase()} for queue: ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'})`); } } stoppedCount++; checkCompletion(); }); }); } startAllQueueHandlers(queueConfigs) { let startedCount = 0; const totalCount = queueConfigs.length; const checkCompletion = () => { if (startedCount === totalCount) { this.logger.debug(`All ${totalCount} handler(s) for queue ${queueConfigs[0].queueParams.name} have been started (ACTIVE state)`); } }; queueConfigs.forEach((queueParsed) => { if (this.messageHandlerRunner.isMessageHandlerRunning(queueParsed)) { this.logger.debug(`Message handler already running for queue: ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'})`); startedCount++; checkCompletion(); return; } const handlerConfig = this.messageHandlerRunner.getMessageHandler(queueParsed); if (!handlerConfig) { this.logger.debug(`No handler configuration found for queue: ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'}), skipping`); startedCount++; checkCompletion(); return; } this.messageHandlerRunner.startMessageHandler(queueParsed, (err, wasStarted) => { if (err) { this.logger.error(`Failed to start message handler for queue ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'}):`, err); } else { if (wasStarted) { this.logger.debug(`Message handler started for queue: ${queueParsed.queueParams.name} (group: ${queueParsed.groupId || 'default'})`); } } startedCount++; checkCompletion(); }); }); } isQueueStopped(queueParams) { const queueKey = this.getQueueKey(queueParams); return this.stoppedQueues.has(queueKey); } isQueuePaused(queueParams) { const queueKey = this.getQueueKey(queueParams); return this.pausedQueues.has(queueKey); } isQueueLocked(queueParams) { const queueKey = this.getQueueKey(queueParams); return this.lockedQueues.has(queueKey); } isQueueActive(queueParams) { const queueKey = this.getQueueKey(queueParams); return (!this.stoppedQueues.has(queueKey) && !this.pausedQueues.has(queueKey) && !this.lockedQueues.has(queueKey)); } getStoppedQueues() { return Array.from(this.stoppedQueues.values()); } getPausedQueues() { return Array.from(this.pausedQueues.values()); } getLockedQueues() { return Array.from(this.lockedQueues.values()); } shutdown = (cb) => { this.internalEventBus.removeListener('queue.stateChanged', this.onQueueStateChange); this.stoppedQueues.clear(); this.pausedQueues.clear(); this.lockedQueues.clear(); this.logger.debug('QueueStateChangeHandler destroyed'); cb(); }; getQueueKey(queueParams) { if ('queueParams' in queueParams) { return `${queueParams.queueParams.ns}:${queueParams.queueParams.name}`; } return `${queueParams.ns}:${queueParams.name}`; } } //# sourceMappingURL=queue-state-change-handler.js.map