[rabbitmq-discuss] Confirmation IDs

Nagy, Attila bra at fsn.hu
Mon Jul 28 11:25:38 BST 2014

On 07/27/14 21:30, Michael Klishin wrote:
>> Nope, from the record's identifier. I have an incoming task queue
>> (for
>> example a file which is appended with records, or a database which
>> has
>> rows), from which I can have a unique identifier which is always
>> available and can directly point to the record.
>> So counting (because publish doesn't give it back) the sent messages
>> (and resetting the counter on reconnects) and maintaining
>> counter->original message pointers are unnecessary indirections
>> to
>> achieve this functionality.
> Coming up with a good identifier for
> an arbitrary message is much harder and there's no consensus on what's the best
> way to do this.
> Especially if you try to come up with a solution for multiple protocols.
I see three approaches:
1. let the server and the client -independently- count the messages and 
use that (the current solution for AMQP in RabbitMQ)
2. let the server count (or otherwise mark them with a unique ID) the 
messages and return it to the client, so it will know about that
3. let the client specify one

I think the first has many problems, it's not flexible, the client has 
to maintain translation tables and has to count exactly the same way as 
the server.
This way the counter must be implemented in the lowest level (in the 
AMQP library, because it's the only one which knows about the connection 
state, which can reset the counter) and higher levels need to sync with 
that, otherwise they won't be able to tell which messages have been 
How do other libraries work in this regard?

Pika's publisher example for example is both wrong (it will die on 
reconnects due to the counter resetting) and ugly. :)

I've just made a quick peek into the java client, so I may be wrong. I 
guess it has these problems too, the counter can be queried 
independently of the publishing, therefore it can't be used in multi 
threaded environments (well, at least you have to open one channel per 
thread, or put a lock on the client so there won't be a race condition 
between querying the counter and sending the message).

>> But STOMP is not really an option if you want to do serious things
>> in
>> RabbitMQ. :)
> I can't see why not.
I've tried all STOMP brokers and finally stick with RabbitMQ, because it 
was the best in many ways. But as in most of the other brokers, STOMP 
offers a limited control on what the broker does in the background, 
which is unsuitable for a lot of use cases.
For example, for me serious means exact access control. And because 
STOMP does abritrary bindings and declares, the clients can't have 
strict policies, they will have always more power than it's needed with 
>> Isn't it possible to add additional info in the ACK frame without
>> breaking current clients?
>> Or making it only appear when publish has a given pattern? (like
>> with STOMP)
> For AMQP 0-9-1 clients, it is not. STOMP header values can be of arbitrary length and many
> headers are optional. AMQP 0-9-1 methods have a fixed (mandatory) attributes
> and only *some* have optional ones ("extra arguments", as an attribute table).
> Unfortunately, basic.ack is not one of the latter group.
OK, then could you please consider the following?
With basic.publish setting a custom header replaces the message's 
confirm sequence number with the header's value (with type 
compatibility, so this will be a limitation, only 64(?) bit unsigned 
ints could be used) and will basic.ack with that.

I mean this would be a normal publish (if confirms are turned on, it 
will have the current counter as the sequence number):

         properties  =  pika.BasicProperties(app_id='example-publisher',

         self._channel.basic_publish(self.EXCHANGE,  self.ROUTING_KEY,
         self._message_number  +=  1

And this will have 123456 as its sequence number:

         properties  =  pika.BasicProperties(app_id='example-publisher',
                                           headers={'key':'value', 'X-RabbitMQ-confirm-seq':123456})

         self._channel.basic_publish(self.EXCHANGE,  self.ROUTING_KEY,

The consequences are to be borne by the client.

More information about the rabbitmq-discuss mailing list