/// <summary> /// Acknowledge the message arrival and processing, so that RabbitMq can remove it from the queue. /// </summary> /// <param name="msg">The message instance</param> public void Ack(RabbitWorkMessage msg) { if (ConsumerChannel.IsOpen) { ConsumerChannel.BasicAck(msg.DeliveryTag, false); } }
private bool CheckRetryLimit(long retryLimit, RabbitWorkMessage msg) { IBasicProperties properties = msg.BasicProperties; if (retryLimit <= 0) { return(true); } // check dead-letter counter (number of times the message was dlx) long count = msg.GetRetryCount(); // check dlx count against our threshold if (count >= retryLimit) { // move message to dead-letter queue if (String.IsNullOrEmpty(deadLetterQueue)) { // create dead letter queue lock (QueueName) { deadLetterQueue = QueueName + ".dead-letter"; deadLetterQueue = EnsureQueueExists(deadLetterQueue, Mode); } } // publish message to the deadletter queue PublishChannel.BasicPublish("", deadLetterQueue, (IBasicProperties)properties.Clone(), msg.Body); // delete message Ack(msg); return(false); } return(true); }
/// <summary> /// Get messages from the queue. /// </summary> /// <param name="millisecondsTimeout">The wait timeout in milliseconds for a message to arrive. -1 for infinite timeout</param> /// <param name="noAck">If the acknowledgement will be manual (noAck == false) or automatic (true).</param> public IEnumerable <RabbitWorkMessage> Get(int millisecondsTimeout, bool noAck = false) { RabbitMQ.Client.Events.BasicDeliverEventArgs item; bool done = false; while (!done) { done = true; using (var sub = new RabbitMQ.Client.MessagePatterns.Subscription(ConsumerChannel, QueueName, noAck)) { while (sub.Next(millisecondsTimeout, out item)) { if (item == null) { // in case of a connection close, the item will be null and we should re-subscribe done = false; break; } // if the message is within the retry threshold, proceed... var msg = new RabbitWorkMessage(this, item); if (CheckRetryLimit(_maxRetry, msg)) { yield return(msg); } } } } }
/// <summary> /// Negative acknowledge the message, the message will be returned to the queue or send to dead letter exchange. /// </summary> /// <param name="msg">The message instance</param> /// <param name="requeue">False will send to dead letter exchange, true will send back to the queue.</param> private void Nack(RabbitWorkMessage msg, bool requeue = false) { if (ConsumerChannel.IsOpen) { // check max retry limit if (!requeue && !CheckRetryLimit(_maxRetry - 1, msg)) { return; } ConsumerChannel.BasicNack(msg.DeliveryTag, false, requeue); } }
/// <summary> /// Rejects the message and returns it to the queue. This does not count against the maxRetry counter. /// </summary> /// <param name="msg">The message instance</param> public void Requeue(RabbitWorkMessage msg) { Nack(msg, true); }
/// <summary> /// Negative acknowledge the message, the message will be marked as a try and send to dead letter exchange according to the maxRetry threshold. /// </summary> /// <param name="msg">The message instance</param> public void Nack(RabbitWorkMessage msg) { Nack(msg, false); }