redis-smq
Version:
A simple high-performance Redis message queue for Node.js.
141 lines • 5.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DequeueMessage = void 0;
const os = require("os");
const types_1 = require("../../../../types");
const redis_keys_1 = require("../../../common/redis-keys/redis-keys");
const redis_smq_common_1 = require("redis-smq-common");
const events_1 = require("../../../common/events/events");
const message_1 = require("../../message/message");
const queue_rate_limit_1 = require("../../queue-manager/queue-rate-limit");
const queue_1 = require("../../queue-manager/queue");
const redis_client_1 = require("../../../common/redis-client/redis-client");
const queue_not_found_error_1 = require("../../queue-manager/errors/queue-not-found.error");
const IPAddresses = (() => {
var _a;
const nets = os.networkInterfaces();
const addresses = [];
for (const netInterface in nets) {
const addr = (_a = nets[netInterface]) !== null && _a !== void 0 ? _a : [];
for (const netAddr of addr) {
if (netAddr.family === 'IPv4' && !netAddr.internal) {
addresses.push(netAddr.address);
}
}
}
return addresses;
})();
class DequeueMessage {
constructor(messageHandler, redisClient) {
this.queueRateLimit = null;
this.queueType = null;
this.messageHandler = messageHandler;
this.redisClient = redisClient;
this.queue = messageHandler.getQueue();
this.consumerId = messageHandler.getConsumerId();
this.redisKeys = redis_keys_1.redisKeys.getQueueConsumerKeys(this.queue, this.consumerId);
this.ticker = new redis_smq_common_1.Ticker(() => this.dequeue());
}
dequeueMessageWithPriority(cb) {
this.redisClient.zpophgetrpush(this.redisKeys.keyQueuePendingPriorityMessageWeight, this.redisKeys.keyQueuePendingPriorityMessages, this.redisKeys.keyQueueProcessing, cb);
}
waitForMessage(cb) {
this.redisClient.brpoplpush(this.redisKeys.keyQueuePending, this.redisKeys.keyQueueProcessing, 0, cb);
}
dequeueMessage(cb) {
this.redisClient.rpoplpush(this.redisKeys.keyQueuePending, this.redisKeys.keyQueueProcessing, cb);
}
dequeue() {
const cb = (err, reply) => {
if (err) {
this.ticker.abort();
this.messageHandler.handleError(err);
}
else if (typeof reply === 'string') {
const message = message_1.Message.createFromMessage(reply);
this.messageHandler.emit(events_1.events.MESSAGE_RECEIVED, message);
}
else {
this.ticker.nextTick();
}
};
const deq = () => {
if (this.isPriorityQueuingEnabled())
this.dequeueMessageWithPriority(cb);
else
this.dequeueMessage(cb);
};
if (this.isPriorityQueuingEnabled() || this.queueRateLimit) {
if (this.queueRateLimit) {
queue_rate_limit_1.QueueRateLimit.hasExceeded(this.redisClient, this.queue, this.queueRateLimit, (err, isExceeded) => {
if (err)
this.messageHandler.handleError(err);
else if (isExceeded)
this.ticker.nextTick();
else
deq();
});
}
else
deq();
}
else {
this.waitForMessage(cb);
}
}
isPriorityQueuingEnabled() {
return this.queueType === types_1.EQueueType.PRIORITY_QUEUE;
}
run(cb) {
redis_smq_common_1.async.waterfall([
(cb) => {
const { keyQueues, keyQueueConsumers, keyConsumerQueues, keyQueueProcessing, keyProcessingQueues, keyQueueProcessingQueues, } = this.redisKeys;
const consumerInfo = {
ipAddress: IPAddresses,
hostname: os.hostname(),
pid: process.pid,
createdAt: Date.now(),
};
this.redisClient.runScript(redis_client_1.ELuaScriptName.INIT_CONSUMER_QUEUE, [
keyQueues,
keyQueueConsumers,
keyConsumerQueues,
keyProcessingQueues,
keyQueueProcessingQueues,
], [
this.consumerId,
JSON.stringify(consumerInfo),
JSON.stringify(this.queue),
keyQueueProcessing,
], (err, reply) => {
if (err)
cb(err);
else if (!reply)
cb(new queue_not_found_error_1.QueueNotFoundError());
else
cb();
});
},
(cb) => {
queue_1.Queue.getSettings(this.messageHandler.getConfig(), this.redisClient, this.queue, (err, reply) => {
var _a;
if (err)
cb(err);
else if (!reply)
cb(new redis_smq_common_1.errors.EmptyCallbackReplyError());
else {
this.queueType = reply.type;
this.queueRateLimit = (_a = reply.rateLimit) !== null && _a !== void 0 ? _a : null;
cb();
}
});
},
], cb);
}
quit(cb) {
this.ticker.once(events_1.events.DOWN, cb);
this.ticker.quit();
}
}
exports.DequeueMessage = DequeueMessage;
//# sourceMappingURL=dequeue-message.js.map