UNPKG

@team-supercharge/nest-amqp

Version:
129 lines (128 loc) 4.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageControl = void 0; const util_1 = require("../util"); /** * Class to manage the state of a message transfer and it's status. * * @public */ class MessageControl { /** * @constructor * @param {EventContext} context Event context received from Rhea related to the message */ constructor(context) { this.context = context; /** * Indicate if the message has already been processed. * If it is, do not process it again. * * @private * @property */ this.handled = false; } /** * Use `accept` when message has been handled normally. * * * NOTE: When no explicit `accept` / `reject` / `release` call has been made * in the callback, message will be automatically accepted. */ accept() { if (this.handled) { logger.log('message already handled'); return; } logger.verbose('accepting message'); this.context.delivery.accept(); this.handleSettlement(); } /** * Use `reject` when message was unprocessable. It contained either malformed * or semantically incorrect data. In other words it can't be successfully * processed in the future without modifications. * * NOTE: With ActiveMQ `reject` will result in the same retry cycle as the * `release` settlement due to technical limitations. Regardless, please * always use the appropriate settlement. * * @param {string|object} reason reason to reject message */ reject(reason) { if (this.handled) { logger.log('message already handled'); return; } logger.verbose(`rejecting message with reason: ${reason.toString()}`); // condition and description will not be displayed anywhere const error = { condition: 'amqp:precondition-failed', description: this.getRejectReason(reason), }; this.context.delivery.reject(error); this.handleSettlement(); } /** * Use release when a temporary problem happened during message handling, e.g. * could not save record to DB, 3rd party service errored, etc. The message is * not malformed and theoretically can be processed at a later time without * modifications. * * NOTE: with ActiveMQ `release` will result in the same retry cycle as the * `reject` settlement due to technical limitations. Regardless, please * always use the appropriate settlement. */ release() { if (this.handled) { logger.log('message already handled'); return; } logger.verbose('releasing message'); // NOTE: need to be handled this way to trigger retry logic this.context.delivery.release({ undeliverable_here: true, delivery_failed: false, }); this.handleSettlement(); } /** * Tells you whether the message has already been processed or not. * * @return {boolean} The message has already been processed or not */ isHandled() { return this.handled; } /** * Marking Message as handled, signaling that we are ready for the next message * * @private */ handleSettlement() { // need to add a credit after successful handling this.context.receiver.addCredit(1); // set as already handled this.handled = true; } /** * AMQ can only handle string reason messages, need to parse the message * * @param {string | object} reason Reason for rejecting the message * @returns {string} parsed message * * @private */ getRejectReason(reason) { try { return typeof reason !== 'string' ? JSON.stringify(reason) : reason; } catch (error) { logger.error(`could not parse error reason: ${reason}`); return 'unknown'; } } } exports.MessageControl = MessageControl; const logger = new util_1.Logger(util_1.getLoggerContext(MessageControl.name));