1

I have a few questions on coding in RabbitMQ... I'm not new to this world and have got questions based on a design provided to me for implementation...

  • If I send BasicAck or BasicAack from Consumer, does it only remove the corresponding message from the queue or will it deliver Ack to the Publisher?
  • How do I ensure that Publisher sends message to Server only when Consumer is ready for processing?

The design says Publisher needs to wait and know when the processing of Consumer is completed to do certain task on client side (depending on success / failure).

I have tried below code but dequeue immediately removed message from queue without I send any Ack or Nack. I'm confused

publisher code:

using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare("test", durable, false, false, null);
                    channel.TxSelect();
                    var properties = channel.CreateBasicProperties();
                    properties.SetPersistent(true);

                    string message = "Hello World!";
                    var body = Encoding.UTF8.GetBytes(message);



                    channel.BasicPublish("", "test", properties, body);
                    channel.TxCommit();
                    Console.WriteLine(" [x] Sent {0}", message);
                }
            }

Consumer code

 using (var connection = factory.CreateConnection())
        {
            using (var channel = connection.CreateModel())
            {
                channel.QueueDeclare("test", durable, false, false, null);

                var consumer = new QueueingBasicConsumer(channel);
                channel.BasicConsume("test", true, consumer);

                Console.WriteLine(" [*] Waiting for messages." +
                                         "To exit press CTRL+C");
                while (true)
                {
                    var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();

                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(" [x] Received {0}", message);
                }
            }
        }

Note: I realized that channel.BasicConsume("test", true, consumer); has noAck to true. I changed this to channel.BasicConsume("test", false, consumer);

I can see the message is removed from the queue when I used channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); But, how does Publisher know that the Consumer processed it successfully?

techspider
  • 3,370
  • 13
  • 37
  • 61

3 Answers3

4

How do I ensure that Publisher sends message to Server only when Consumer is ready for processing?

You can't. And more important, you shouldn't. The point of using a messaging architecture is to forget about this kind of problems. Check this.

Also, RabbitMQ will store this messages for you until someone will be ready to process them if the queue is durable.

But, how does Publisher know that the Consumer processed it successfully?

No, will not. The ack is only between RabbitMQ and your consumer or between RabbitMQ and your producer. Check this for some details on ack/nack.

What you want to achieve here, if I can understand you correctly, is a kind of "chatty" architecture, where the consumer is also a producer of "response messages" for the publisher, messages like "hey, I'm done with message XX, everything is ok".

The easies way to do this is to set your consumer to be also a producer, and your producer to be also a consumer. You simply need to add a guid or an unique id of some sort to the message, and when you're done with it, you will send a message on another queue with that id as content to inform the original publisher (which is a consumer of this "response" queue) that the work has completed successfully.

Hope it helps :)

Luca Ghersi
  • 3,261
  • 18
  • 32
  • thanks; I know you have provided a solution to my problem; which one is standard or traditional way implementation? I hope the first one but not the "chatty" architecture! – techspider Mar 21 '16 at 13:28
  • If you need to let the producer know that you consumer "did" the job, a response on the channel is required; the response can be on the same queue or on another queue, but is another message to send. Otherwise you can check sagas, check this http://docs.masstransit-project.com/en/latest/overview/saga.html but are a little bit more complicated (and you need masstransit). Maybe you can rethink your architecture trying to remove the necessity for a response message :) – Luca Ghersi Mar 21 '16 at 13:33
  • I agree with your response completely; It depends on how our Architect wants ;) thanks for your help – techspider Mar 21 '16 at 13:35
1

This is kind of a duplicated question. Check this thread, which is a similar question with a correct answer: Why doesn't Channel.waitForConfirmsOrDie block?

Community
  • 1
  • 1
Teddy Ma
  • 1,126
  • 6
  • 12
1

Or you can use the RPC pattern

https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html

Ozkan
  • 3,880
  • 9
  • 47
  • 78