redis-smq
Version:
A simple high-performance Redis message queue for Node.js.
99 lines • 4.42 kB
JavaScript
import { Timer } from 'redis-smq-common';
import { MultiplexedMessageHandler } from '../message-handler/message-handler/multiplexed-message-handler.js';
import { MessageHandlerRunner } from './message-handler-runner.js';
export class MultiplexedMessageHandlerRunner extends MessageHandlerRunner {
timer;
index = 0;
activeMessageHandler = null;
tickIntervalMs = 1000;
constructor(consumer, redisClient, eventBus) {
super(consumer, redisClient, eventBus);
this.logger.info(`Initializing MultiplexedMessageHandlerRunner with ID: ${this.id}`);
this.timer = new Timer();
this.timer.on('error', (err) => {
this.logger.error(`Timer error: ${err.message}`);
this.handleError(err);
});
this.logger.debug('Timer initialized and error handler registered');
}
nextTick() {
if (!this.isRunning()) {
this.logger.debug('nextTick called while not running, ignoring');
return;
}
this.activeMessageHandler = null;
this.timer.reset();
this.logger.debug(`Scheduling next message handler execution in ${this.tickIntervalMs}ms`);
this.timer.setTimeout(() => this.execNextMessageHandler(), this.tickIntervalMs);
}
getNextMessageHandler() {
const count = this.messageHandlerInstances.length;
if (count === 0) {
this.logger.debug('No message handlers registered');
return null;
}
if (this.index >= count) {
this.index = 0;
}
const handler = this.messageHandlerInstances[this.index];
this.logger.debug(`Selected message handler at index ${this.index} (ID: ${handler?.getId?.() ?? 'N/A'})`);
this.index = (this.index + 1) % count;
return handler;
}
execNextMessageHandler = () => {
if (!this.isRunning()) {
this.logger.debug('execNextMessageHandler called while not running, ignoring');
return;
}
this.activeMessageHandler = this.getNextMessageHandler();
if (this.activeMessageHandler) {
if (this.activeMessageHandler.isRunning()) {
this.logger.debug(`Triggering dequeue on active handler (ID: ${this.activeMessageHandler.getId()})`);
this.activeMessageHandler.dequeue();
}
else {
this.logger.debug(`Active handler (ID: ${this.activeMessageHandler.getId()}) is not running, scheduling next tick`);
this.nextTick();
}
}
else {
this.logger.debug('No active handler available, scheduling next tick');
this.nextTick();
}
};
createMessageHandlerInstance(handlerParams) {
this.logger.debug(`Creating MultiplexedMessageHandler for queue: ${JSON.stringify(handlerParams.queue)}`);
const instance = new MultiplexedMessageHandler(this.consumer, this.redisClient, handlerParams, this.eventBus, this.execNextMessageHandler);
this.messageHandlerInstances.push(instance);
this.logger.info(`Created MultiplexedMessageHandler (ID: ${instance.getId()}) for queue: ${handlerParams.queue.queueParams.name}. Total: ${this.messageHandlerInstances.length}`);
return instance;
}
shutdownMessageHandler(messageHandler, cb) {
const queue = messageHandler.getQueue();
this.logger.debug(`Shutting down handler (ID: ${messageHandler.getId()}) for queue: ${JSON.stringify(queue)}`);
super.shutdownMessageHandler(messageHandler, () => {
if (messageHandler === this.activeMessageHandler) {
this.logger.debug('Shut down active handler, scheduling next tick');
this.nextTick();
}
cb();
});
}
goingUp() {
this.logger.info('MultiplexedMessageHandlerRunner going up');
return super.goingUp().concat([
(cb) => {
this.logger.debug('Starting message handler execution cycle');
this.execNextMessageHandler();
cb();
},
]);
}
goingDown() {
this.logger.info('MultiplexedMessageHandlerRunner going down');
this.logger.debug('Resetting timer during shutdown');
this.timer.reset();
return super.goingDown();
}
}
//# sourceMappingURL=multiplexed-message-handler-runner.js.map