redis-smq
Version:
A simple high-performance Redis message queue for Node.js.
140 lines • 5.49 kB
JavaScript
import { async, Runnable } from 'redis-smq-common';
import { ConsumerConsumeMessageHandlerAlreadyExistsError } from '../errors/index.js';
import { MessageHandler } from '../message-handler/message-handler/message-handler.js';
import { eventBusPublisher } from './event-bus-publisher.js';
export class MessageHandlerRunner extends Runnable {
consumer;
redisClient;
logger;
messageHandlerInstances = [];
messageHandlers = [];
eventBus;
constructor(consumer, redisClient, logger, eventBus) {
super();
this.consumer = consumer;
this.redisClient = redisClient;
this.logger = logger;
this.eventBus = eventBus;
if (this.eventBus) {
eventBusPublisher(this, this.eventBus, logger);
}
}
getLogger() {
return this.logger;
}
getMessageHandlerInstance(queue) {
const { queueParams, groupId } = queue;
return this.messageHandlerInstances.find((i) => {
const handlerQueue = i.getQueue();
return (handlerQueue.queueParams.name === queueParams.name &&
handlerQueue.queueParams.ns === queueParams.ns &&
handlerQueue.groupId === groupId);
});
}
getMessageHandler(queue) {
const { queueParams, groupId } = queue;
return this.messageHandlers.find((i) => i.queue.queueParams.name === queueParams.name &&
i.queue.queueParams.ns === queueParams.ns &&
i.queue.groupId === groupId);
}
createMessageHandlerInstance(handlerParams) {
const instance = new MessageHandler(this.consumer, this.redisClient, this.logger, handlerParams, true, this.eventBus);
instance.on('consumer.messageHandler.error', (err, consumerId, queue) => {
this.removeMessageHandler(queue, () => {
this.logger.error(err);
});
});
this.messageHandlerInstances.push(instance);
this.logger.info(`Created a new instance (ID: ${instance.getId()}) for MessageHandler (${JSON.stringify(handlerParams)}).`);
return instance;
}
runMessageHandler(handlerParams, cb) {
const handler = this.createMessageHandlerInstance(handlerParams);
handler.run((err) => {
if (err)
this.removeMessageHandler(handlerParams.queue, () => cb(err));
else {
cb();
}
});
}
shutdownMessageHandler(messageHandler, cb) {
const queue = messageHandler.getQueue();
messageHandler.shutdown(() => {
this.messageHandlerInstances = this.messageHandlerInstances.filter((handler) => {
const iQueue = handler.getQueue();
return !(iQueue.queueParams.name === queue.queueParams.name &&
iQueue.queueParams.ns === queue.queueParams.ns &&
iQueue.groupId === queue.groupId);
});
cb();
});
}
runMessageHandlers = (cb) => {
async.each(this.messageHandlers, (handlerParams, _, done) => {
this.runMessageHandler(handlerParams, done);
}, cb);
};
shutDownMessageHandlers = (cb) => {
async.each(this.messageHandlerInstances, (handler, queue, done) => {
this.shutdownMessageHandler(handler, () => done());
}, () => {
this.messageHandlerInstances = [];
cb();
});
};
goingUp() {
return super.goingUp().concat([this.runMessageHandlers]);
}
goingDown() {
return [this.shutDownMessageHandlers].concat(super.goingDown());
}
handleError(err) {
if (this.isRunning()) {
this.emit('consumer.messageHandlerRunner.error', err, this.consumer.getId());
}
super.handleError(err);
}
removeMessageHandler(queue, cb) {
const { queueParams, groupId } = queue;
const handler = this.getMessageHandler(queue);
if (!handler)
cb();
else {
this.messageHandlers = this.messageHandlers.filter((handler) => {
const handerQueue = handler.queue;
return !(queueParams.name === handerQueue.queueParams.name &&
queueParams.ns === handerQueue.queueParams.ns &&
groupId === handerQueue.groupId);
});
this.logger.info(`Message handler with parameters (${JSON.stringify(queue)}) has been removed.`);
const handlerInstance = this.getMessageHandlerInstance(queue);
if (handlerInstance)
this.shutdownMessageHandler(handlerInstance, cb);
else
cb();
}
}
addMessageHandler(queue, messageHandler, cb) {
const handler = this.getMessageHandler(queue);
if (handler)
cb(new ConsumerConsumeMessageHandlerAlreadyExistsError());
else {
const handlerParams = {
queue,
messageHandler,
};
this.messageHandlers.push(handlerParams);
this.logger.info(`Message handler with parameters (${JSON.stringify(handlerParams)}) has been registered.`);
if (this.isRunning()) {
this.runMessageHandler(handlerParams, cb);
}
else
cb();
}
}
getQueues() {
return this.messageHandlers.map((i) => i.queue);
}
}
//# sourceMappingURL=message-handler-runner.js.map