UNPKG

redis-smq

Version:

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

160 lines 7.75 kB
import { ERedisScriptName } from '../../common/redis/scripts.js'; import { redisKeys } from '../../common/redis/redis-keys/redis-keys.js'; import { EMessageProperty, EMessagePropertyStatus, } from '../../message/index.js'; import { EQueueOperationalState, EQueueProperty, EQueueType, } from '../../queue-manager/index.js'; import { ConsumerGroupNotFoundError, InvalidQueueStateError, InvalidQueueTypeError, MessageAlreadyExistsError, MessagePriorityRequiredError, PriorityQueuingNotEnabledError, QueueLockedError, QueueNotFoundError, QueueStoppedError, UnexpectedScriptReplyError, } from '../../errors/index.js'; export function _publishMessage(redisClient, message, logger, cb) { const messageState = message.getMessageState(); const messageId = message.getId(); const destinationQueue = message.getDestinationQueue(); const queueName = `${destinationQueue.name}@${destinationQueue.ns}`; const consumerGroupId = message.getConsumerGroupId(); logger.debug(`Enqueuing message ${messageId} to queue ${queueName}${consumerGroupId ? ` for consumer group ${consumerGroupId}` : ''}`); const keys = redisKeys.getQueueKeys(destinationQueue.ns, destinationQueue.name, consumerGroupId); const { keyMessage } = redisKeys.getMessageKeys(messageId); const messagePriority = message.producibleMessage.getPriority(); logger.debug(`Message ${messageId} details: priority=${messagePriority ?? 'none'}, queue=${queueName}`); const scheduledTimestamp = message.getNextScheduledTimestamp(); const messageStatus = scheduledTimestamp ? EMessagePropertyStatus.SCHEDULED : EMessagePropertyStatus.PENDING; const queuePropertyValues = [ 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, ]; const schedulingValues = [ messagePriority ?? '', scheduledTimestamp, EMessagePropertyStatus.SCHEDULED, EMessagePropertyStatus.PENDING, ]; const messagePropertyKeys = [ 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, ]; const messagePropertyValues = [ messageId, messageStatus, JSON.stringify(message.toJSON()), messageState.getScheduledAt() ?? '', messageState.getPublishedAt() ?? '', messageState.getProcessingStartedAt() ?? '', messageState.getDeadLetteredAt() ?? '', messageState.getAcknowledgedAt() ?? '', messageState.getUnacknowledgedAt() ?? '', messageState.getLastUnacknowledgedAt() ?? '', messageState.getLastScheduledAt() ?? '', messageState.getRequeuedAt() ?? '', messageState.getRequeueCount(), messageState.getLastRequeuedAt() ?? '', messageState.getLastRetriedAttemptAt() ?? '', Number(messageState.isScheduledCronFired()), messageState.getAttempts(), messageState.getScheduledRepeatCount(), Number(messageState.getExpired()), messageState.getEffectiveScheduledDelay(), messageState.getScheduledTimes(), messageState.getScheduledMessageParentId() ?? '', messageState.getRequeuedMessageParentId() ?? '', messageState.getLastProcessedAt() ?? '', ]; const scriptArgs = [ ...queuePropertyValues, ...schedulingValues, ...messagePropertyKeys, ...messagePropertyValues, consumerGroupId ?? '', '', ]; redisClient.runScript(ERedisScriptName.PUBLISH_MESSAGE, [ keys.keyQueueProperties, keys.keyQueuePriority, keys.keyQueuePending, keys.keyQueueScheduled, keys.keyQueuePublished, keys.keyQueueConsumerGroups, keyMessage, ], scriptArgs, (err, reply) => { if (err) { logger.error(`Failed to publish message ${messageId}`, err); return cb(err); } switch (reply) { case 'OK': logger.debug(`Successfully published message ${messageId} to queue ${queueName}`); return cb(); case 'QUEUE_NOT_FOUND': logger.error(`Queue ${queueName} not found for message ${messageId}`); return cb(new QueueNotFoundError({ metadata: { queue: destinationQueue, }, })); case 'CONSUMER_GROUP_NOT_FOUND': logger.error(`Consumer group ${consumerGroupId} not found for queue ${queueName}`); return cb(new ConsumerGroupNotFoundError()); case 'MESSAGE_PRIORITY_REQUIRED': logger.error(`Priority required for message ${messageId} but not provided`); return cb(new MessagePriorityRequiredError()); case 'MESSAGE_ALREADY_EXISTS': logger.error(`A message with ${messageId} already exists`); return cb(new MessageAlreadyExistsError()); case 'PRIORITY_QUEUING_NOT_ENABLED': logger.error(`Priority queuing not enabled for queue ${queueName}`); return cb(new PriorityQueuingNotEnabledError()); case 'UNKNOWN_QUEUE_TYPE': logger.error(`Unknown queue type for queue ${queueName}`); return cb(new InvalidQueueTypeError()); case 'QUEUE_STOPPED': logger.error(`Queue ${queueName} is in STOPPED state, cannot publish message ${messageId}`); return cb(new QueueStoppedError({ metadata: { queue: destinationQueue } })); case 'QUEUE_LOCKED': logger.error(`Queue ${queueName} is in LOCKED state, cannot publish message ${messageId}. Provide a valid lock ID to publish.`); return cb(new QueueLockedError({ metadata: { queue: destinationQueue } })); case 'QUEUE_INVALID_STATE': logger.error(`Queue ${queueName} is in invalid state, cannot publish message ${messageId}`); return cb(new InvalidQueueStateError({ metadata: { queue: destinationQueue, }, })); default: logger.error(`Unknown error while publishing message ${messageId}: ${reply}`); return cb(new UnexpectedScriptReplyError({ metadata: { reply } })); } }); } //# sourceMappingURL=_publish-message.js.map