[rabbitmq-discuss] Redelivery of unacknowledged messages

Ben Hood 0x6e6562 at gmail.com
Tue Sep 30 01:59:33 BST 2008


Jonatan,

On Mon, Sep 29, 2008 at 10:34 PM, Jonatan Kallus <jonatan at heysan.com> wrote:
> I get the feeling that this should be a rather basic question, but I have
> searched the mailing list and the AMQP specification without finding
> answers.

I did answer this last week, but it was off list and I'm still waiting
for confirmation to turn it into a list topic.

> For how long does the server wait for acknowledgment from a subscriber (when
> acknowledgment is required)?
>
> When are unacknowledged messages redelivered?

After the channel in which the initial receive has been closed and a
new channel has been setup.

> In my set up, using the java api for a single consumer and the stomp gateway
> and a php stomp client for sending messages to the queue, messages do not
> seem to get redelivered until the consumer is restarted.

This example code may illustrate the mechanism:

package com.acme;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.GetResponse;
import com.rabbitmq.client.MessageProperties;

public class AckExample {

   // Using JDK assertions: add -ea flag to the interpreter
   public static void main(String[] args) throws Exception {
       final Connection con = new
ConnectionFactory().newConnection("0.0.0.0", 5672);
       Channel channel = con.createChannel();
       String q = "foo" + System.currentTimeMillis();
       byte[] msg = ("bar" + System.currentTimeMillis()).getBytes();
       channel.queueDeclare(1, q);
       // Send 1 message
       channel.basicPublish(1, "", q, MessageProperties.BASIC, msg);
       // Synchronous receive with acknowledgements turned on
       GetResponse response1 = channel.basicGet(1, q, false);
       assert null != response1.getBody();
       assert false == response1.getEnvelope().isRedeliver();
       // Deliberately forget to ack the message and nuke the channel
       channel.close(200, "hasta la vista, baby");
       // Start a new channel
       channel = con.createChannel();
       // Get the same message
       GetResponse response2 = channel.basicGet(1, q, false);
       assert null != response2.getBody();
       assert true == response2.getEnvelope().isRedeliver();
       channel.close(200, "hasta la vista, baby");
       con.close();
       assert response1.getEnvelope().getDeliveryTag() ==
response2.getEnvelope().getDeliveryTag();
   }
}

This uses the fact that an un-acked message will get redelivered on a
different channel if the original get command set the to no-ack flag
to false and no ack was received on this channel. Crude, but it works.

HTH,

Ben




More information about the rabbitmq-discuss mailing list