redis-smq
Version:
A simple high-performance Redis message queue for Node.js.
154 lines • 6.16 kB
JavaScript
import { async, CallbackEmptyReplyError, } from 'redis-smq-common';
import { _deleteMessage } from '../../message/_/_delete-message.js';
import { _parseQueueExtendedParams } from '../../queue/_/_parse-queue-extended-params.js';
import { _validateQueueExtendedParams } from '../_/_validate-queue-extended-params.js';
export class QueueMessagesManagerAbstract {
redisClient;
message;
requireGroupId = false;
redisKey;
messageStorage;
constructor(redisClient, messagesStorage, message, redisKey) {
this.redisClient = redisClient;
this.messageStorage = messagesStorage;
this.message = message;
this.redisKey = redisKey;
}
getTotalPages(pageSize, totalItems) {
if (pageSize <= 0) {
return 1;
}
const totalPages = Math.ceil(totalItems / pageSize);
return totalPages > 0 ? totalPages : 1;
}
getPaginationParams(cursor, totalItems, pageSize) {
const totalPages = this.getTotalPages(pageSize, totalItems);
const currentPage = cursor < 1 || cursor > totalPages ? 1 : cursor;
const offsetStart = (currentPage - 1) * pageSize;
const offsetEnd = offsetStart + pageSize - 1;
return { offsetStart, offsetEnd, currentPage, totalPages };
}
getMessagesIds(queue, page, pageSize, cb) {
async.waterfall([
(next) => this.messageStorage.count(queue, this.redisKey, next),
(totalItems, next) => {
const { currentPage, offsetStart, offsetEnd, totalPages } = this.getPaginationParams(page, totalItems, pageSize);
const nextCursor = currentPage < totalPages ? currentPage + 1 : 0;
if (totalItems === 0) {
return next(null, {
cursor: nextCursor,
totalItems,
items: [],
});
}
this.messageStorage.fetchItems(queue, this.redisKey, offsetStart, offsetEnd, (err, items) => {
if (err)
return next(err);
next(null, {
cursor: nextCursor,
totalItems,
items: items ?? [],
});
});
},
], cb);
}
purge(queue, cb) {
const parsedParams = _parseQueueExtendedParams(queue);
if (parsedParams instanceof Error)
return cb(parsedParams);
this.redisClient.getSetInstance((err, client) => {
if (err)
return cb(err);
if (!client)
return cb(new CallbackEmptyReplyError());
_validateQueueExtendedParams(client, parsedParams, this.requireGroupId, (err) => {
if (err)
return cb(err);
this._purgeMessages(client, parsedParams, cb);
});
});
}
_purgeMessages(client, parsedParams, cb) {
const purgeBatch = (cursor = '0') => {
async.waterfall([
(next) => {
this.getMessagesIds(parsedParams, Number(cursor), 1000, next);
},
(page, next) => {
const { items, cursor: nextCursor } = page;
if (items.length === 0) {
return next(null, String(nextCursor));
}
_deleteMessage(client, items, (err) => {
if (err)
return next(err);
next(null, String(nextCursor));
});
},
], (err, nextCursor) => {
if (err)
return cb(err);
if (nextCursor !== '0') {
purgeBatch(String(nextCursor));
}
else {
cb();
}
});
};
purgeBatch('0');
}
getMessages(queue, page, pageSize, cb) {
const parsedParams = _parseQueueExtendedParams(queue);
if (parsedParams instanceof Error)
return cb(parsedParams);
this.redisClient.getSetInstance((err, client) => {
if (err)
return cb(err);
if (!client)
return cb(new CallbackEmptyReplyError());
_validateQueueExtendedParams(client, parsedParams, this.requireGroupId, (err) => {
if (err)
return cb(err);
this.getMessagesIds(parsedParams, page, pageSize, (err, pageResult) => {
if (err)
return cb(err);
if (!pageResult)
return cb(new CallbackEmptyReplyError());
if (pageResult.items.length === 0) {
return cb(null, { ...pageResult, items: [] });
}
this.message.getMessagesByIds(pageResult.items, (err, messages) => {
if (err)
return cb(err);
cb(null, { ...pageResult, items: messages ?? [] });
});
});
});
});
}
countMessages(queue, cb) {
this.redisClient.getSetInstance((err, client) => {
if (err)
return cb(err);
if (!client)
return cb(new CallbackEmptyReplyError());
const parsedParams = _parseQueueExtendedParams(queue);
if (parsedParams instanceof Error)
return cb(parsedParams);
_validateQueueExtendedParams(client, parsedParams, this.requireGroupId, (err) => {
if (err)
return cb(err);
this.messageStorage.count(parsedParams, this.redisKey, cb);
});
});
}
shutdown(cb) {
async.waterfall([
(next) => this.message.shutdown(next),
(next) => this.redisClient.shutdown(next),
], cb);
}
}
//# sourceMappingURL=queue-messages-manager-abstract.js.map