redis-smq
Version:
A high-performance, reliable, and scalable message queue for Node.js.
140 lines • 6.59 kB
JavaScript
import { async, CallbackEmptyReplyError, } from 'redis-smq-common';
import { ERedisScriptName } from '../../common/redis/scripts.js';
import { redisKeys } from '../../common/redis/redis-keys/redis-keys.js';
import { EQueueOperationalState, EQueueProperty, EQueueType, } from '../../queue-manager/index.js';
import { MessageNotFoundError, MessageNotRequeuableError, RequeueMessageScriptError, UnexpectedScriptReplyError, } from '../../errors/index.js';
import { _fromMessage } from './_from-message.js';
import { _getMessage } from './_get-message.js';
import { EMessageProperty, EMessagePropertyStatus, } from '../../message/index.js';
import { _validateOperation } from '../../queue-operation-validator/_/_validate-operation.js';
import { EQueueOperation } from '../../queue-operation-validator/index.js';
export function _requeueMessage(redisClient, messageId, cb) {
async.waterfall([
(cb) => {
_getMessage(redisClient, messageId, (err, message) => {
if (err)
return cb(err);
if (!message)
return cb(new CallbackEmptyReplyError());
if (![
EMessagePropertyStatus.ACKNOWLEDGED,
EMessagePropertyStatus.DEAD_LETTERED,
].includes(message.getStatus())) {
return cb(new MessageNotRequeuableError());
}
cb(null, message);
});
},
(message, cb) => {
const queue = message.getDestinationQueue();
_validateOperation(redisClient, queue, EQueueOperation.REQUEUE_MESSAGE, (err) => {
if (err)
return cb(err);
cb(null, message);
});
},
(message, cb) => {
const ts = Date.now();
const newMessage = _fromMessage(message);
newMessage.producibleMessage.resetScheduledParams();
const newMessageState = newMessage
.getMessageState()
.setPublishedAt(ts)
.setRequeuedMessageParentId(messageId);
const { keyMessage: keyOriginalMessage } = redisKeys.getMessageKeys(messageId);
const newChildMessageId = newMessageState.getId();
const { keyMessage: keyNewMessage } = redisKeys.getMessageKeys(newChildMessageId);
const destinationQueue = message.getDestinationQueue();
const consumerGroupId = message.getConsumerGroupId();
const { keyQueueProperties, keyQueuePending, keyQueuePriority, keyQueuePublished, keyQueueScheduled, keyQueueConsumerGroups, } = redisKeys.getQueueKeys(destinationQueue.ns, destinationQueue.name, consumerGroupId);
const keys = [
keyQueueProperties,
keyQueuePriority,
keyQueuePending,
keyQueuePublished,
keyQueueScheduled,
keyQueueConsumerGroups,
keyOriginalMessage,
keyNewMessage,
];
const argv = [
EQueueProperty.QUEUE_TYPE,
EQueueProperty.MESSAGES_COUNT,
EQueueProperty.PENDING_MESSAGES_COUNT,
EQueueProperty.SCHEDULED_MESSAGES_COUNT,
EQueueType.PRIORITY_QUEUE,
EQueueType.LIFO_QUEUE,
EQueueType.FIFO_QUEUE,
EQueueProperty.OPERATIONAL_STATE,
EQueueProperty.LOCK_ID,
EQueueOperationalState.ACTIVE,
EQueueOperationalState.PAUSED,
EQueueOperationalState.STOPPED,
EQueueOperationalState.LOCKED,
EMessagePropertyStatus.SCHEDULED,
EMessagePropertyStatus.PENDING,
EMessageProperty.ID,
EMessageProperty.STATUS,
EMessageProperty.MESSAGE,
EMessageProperty.SCHEDULED_AT,
EMessageProperty.PUBLISHED_AT,
EMessageProperty.PROCESSING_STARTED_AT,
EMessageProperty.DEAD_LETTERED_AT,
EMessageProperty.ACKNOWLEDGED_AT,
EMessageProperty.UNACKNOWLEDGED_AT,
EMessageProperty.LAST_UNACKNOWLEDGED_AT,
EMessageProperty.LAST_SCHEDULED_AT,
EMessageProperty.REQUEUED_AT,
EMessageProperty.REQUEUE_COUNT,
EMessageProperty.LAST_REQUEUED_AT,
EMessageProperty.LAST_RETRIED_ATTEMPT_AT,
EMessageProperty.SCHEDULED_CRON_FIRED,
EMessageProperty.ATTEMPTS,
EMessageProperty.SCHEDULED_REPEAT_COUNT,
EMessageProperty.EXPIRED,
EMessageProperty.EFFECTIVE_SCHEDULED_DELAY,
EMessageProperty.SCHEDULED_TIMES,
EMessageProperty.SCHEDULED_MESSAGE_PARENT_ID,
EMessageProperty.REQUEUED_MESSAGE_PARENT_ID,
EMessageProperty.LAST_PROCESSED_AT,
'',
newChildMessageId,
JSON.stringify(newMessage.toJSON()),
message.producibleMessage.getPriority() ?? '',
ts,
message.getMessageState().getRequeuedAt() ?? ts,
ts,
consumerGroupId ?? '',
];
redisClient.runScript(ERedisScriptName.REQUEUE_MESSAGE, keys, argv, (err, reply) => {
if (err)
return cb(err);
if (reply === 1)
return cb(null, newChildMessageId);
if (reply === 0) {
return cb(new MessageNotFoundError({
message: `Could not requeue message ID ${messageId}. Message or consumer group not found.`,
}));
}
if (typeof reply === 'string') {
if (reply.startsWith('REQUEUE_ERROR:')) {
return cb(new RequeueMessageScriptError({
metadata: {
scriptReply: reply,
},
}));
}
return cb(new RequeueMessageScriptError({
metadata: {
scriptReply: reply,
},
}));
}
cb(new UnexpectedScriptReplyError({
metadata: { reply },
}));
});
},
], cb);
}
//# sourceMappingURL=_requeue-message.js.map