UNPKG

redis-smq

Version:

A high-performance, reliable, and scalable message queue for Node.js.

172 lines 7.71 kB
import { async, CallbackInvalidReplyError, } from 'redis-smq-common'; import { EQueueOperationalState, EQueueProperty, EQueueType, } from '../../queue-manager/index.js'; import { redisKeys } from '../../common/redis/redis-keys/redis-keys.js'; import { ERedisScriptName } from '../../common/redis/scripts.js'; import { EMessageProperty, EMessagePropertyStatus, } from '../../message/index.js'; import { _getMessage } from './_get-message.js'; import { MessageNotFoundError, QueueLockedError, QueueNotFoundError, UnexpectedScriptReplyError, } from '../../errors/index.js'; export function _deleteMessage(redisClient, messageId, lockId, cb) { const deleteResponse = { status: 'MESSAGE_NOT_DELETED', stats: { processed: 0, success: 0, notFound: 0, inProcess: 0, }, }; const ids = Array.isArray(messageId) ? messageId : [messageId]; if (!ids.length) { deleteResponse.status = 'OK'; return cb(null, deleteResponse); } const stats = deleteResponse.stats; const messages = []; async.eachOf(ids, (id, _, done) => { _getMessage(redisClient, id, (err, msg) => { if (err) { if (err instanceof MessageNotFoundError) { stats.notFound += 1; stats.processed += 1; return done(); } return done(err); } if (msg) messages.push(msg); done(); }); }, (err) => { if (err) return cb(err); if (!messages.length) { return cb(null, deleteResponse); } const messagesByQueueAndGroup = {}; messages.reduce((acc, msg) => { const queue = msg.getDestinationQueue(); const queueId = `${queue.ns}:${queue.name}`; if (!acc[queueId]) { acc[queueId] = {}; } const consumerGroupId = msg.getConsumerGroupId() ?? '_'; if (!acc[queueId][consumerGroupId]) { acc[queueId][consumerGroupId] = { queue, messages: [], }; } acc[queueId][consumerGroupId].messages.push(msg); return acc; }, messagesByQueueAndGroup); async.eachIn(messagesByQueueAndGroup, (groups, _, done) => { async.eachIn(groups, (item, groupId, done) => { const { queue, messages: batchMessages } = item; const consumerGroupId = groupId === '_' ? null : groupId; const { keyQueueProperties, keyQueuePublished, keyQueuePending, keyQueuePriority, keyQueueScheduled, keyQueueAcknowledged, keyQueueDeadLetter, keyQueueDelayed, keyQueueRequeued, } = redisKeys.getQueueKeys(queue.ns, queue.name, consumerGroupId); const staticKeys = [ keyQueueProperties, keyQueuePublished, keyQueuePending, keyQueuePriority, keyQueueScheduled, keyQueueAcknowledged, keyQueueDeadLetter, keyQueueDelayed, keyQueueRequeued, ]; const staticArgs = [ EQueueProperty.QUEUE_TYPE, EQueueProperty.MESSAGES_COUNT, EQueueProperty.ACKNOWLEDGED_MESSAGES_COUNT, EQueueProperty.DEAD_LETTERED_MESSAGES_COUNT, EQueueProperty.PENDING_MESSAGES_COUNT, EQueueProperty.SCHEDULED_MESSAGES_COUNT, EQueueProperty.DELAYED_MESSAGES_COUNT, EQueueProperty.REQUEUED_MESSAGES_COUNT, EQueueType.PRIORITY_QUEUE, EQueueType.LIFO_QUEUE, EQueueType.FIFO_QUEUE, EMessageProperty.STATUS, EMessagePropertyStatus.PROCESSING, EMessagePropertyStatus.ACKNOWLEDGED, EMessagePropertyStatus.PENDING, EMessagePropertyStatus.SCHEDULED, EMessagePropertyStatus.DEAD_LETTERED, EMessagePropertyStatus.UNACK_DELAYING, EMessagePropertyStatus.UNACK_REQUEUING, EQueueProperty.OPERATIONAL_STATE, EQueueOperationalState.LOCKED, EQueueProperty.LOCK_ID, lockId ?? '', ]; const dynamicKeys = []; for (const msg of batchMessages) { const { keyMessage, keyMessageUnacknowledgementHistory } = redisKeys.getMessageKeys(msg.getId()); dynamicKeys.push(keyMessage, keyMessageUnacknowledgementHistory); } const dynamicArgs = batchMessages.map((msg) => msg.getId()); const keys = [...staticKeys, ...dynamicKeys]; const argv = [...staticArgs, ...dynamicArgs]; redisClient.runScript(ERedisScriptName.DELETE_MESSAGE, keys, argv, (err, reply) => { if (err) return done(err); if (reply === 'QUEUE_LOCKED') { return done(new QueueLockedError({ message: `Cannot delete messages from queue ${queue.name}: Queue is locked`, metadata: { queue: queue, }, })); } if (reply === 'INVALID_LOCK') { return done(new QueueLockedError({ message: `Cannot delete messages from queue ${queue.name}: Invalid lock ID provided`, metadata: { queue: queue, }, })); } if (reply === 'QUEUE_NOT_FOUND') { return done(new QueueNotFoundError({ metadata: { queue, }, })); } if (reply === 'INVALID_ARGS_ERROR') { return done(new UnexpectedScriptReplyError({ message: 'Invalid arguments error in DELETE_MESSAGE script', metadata: { reply, }, })); } if (!Array.isArray(reply) || reply.length !== 4) { return done(new CallbackInvalidReplyError()); } const [processed, success, notFound, inProcess] = reply; stats.processed += processed; stats.success += success; stats.notFound += notFound; stats.inProcess += inProcess; done(); }); }, done); }, (err) => { if (err) return cb(err); if (stats.processed === stats.success && stats.processed > 0) { deleteResponse.status = 'OK'; } else if (stats.success > 0) { deleteResponse.status = 'PARTIAL_SUCCESS'; } else { deleteResponse.status = 'MESSAGE_NOT_DELETED'; } cb(null, deleteResponse); }); }); } //# sourceMappingURL=_delete-message.js.map