[rabbitmq-discuss] Queue delete causes transaction errors

Michael Bridgen mikeb at rabbitmq.com
Tue Jul 13 16:29:11 BST 2010


Hi Aaron,

> I've confirmed that transactions are being aborted due to a queue
> being deleted using an easily-reproducible test case.
> 
> The base-case is an exchange and a 1-1 mapping of a routing key to a
> destination queue.  The client is simply consuming a published message
> and then publishing the next one.  A single client as a consumer is
> enough to repeat the bug.
> 
> We then have a test client which we can use to attach to an exchange
> using a supplied routing key.  It will create its own queue and then
> act as a passive listener, for easy monitoring of traffic.  The queue
> it uses is set to auto-delete. In high-traffic situations, I would
> occasionally see a transaction error in the client.
> 
> I setup a test case today where a listener would open a connection and
> queue, listen for 2 seconds, then disconnect.  I tried combinations of
> auto_delete enabled and disabled, both with and without an explicit
> queue delete call, as well as using transactions and re-using a
> connection versus closing and reconnecting.  I would run this test
> listener while a test client simply published a message to itself
> every time it received one.  The client is using transactions,
> committing after each publish call.  Within a few minutes, no matter
> how my listener was configured, the client would receive a transaction
> error.  I repeated this with the 1.8.0 release.

It looks like there's two races going on here:
  - the queue being autodeleted, and the transaction committing; and
  - the connection dropping, and the transaction committing.

In the first case, the transaction commit fails because the queue has 
gone away and it can no longer route the message to it.  I'm less 
certain about the second; I think it may be because the queue tries to 
deliver the message on tx.commit, and the connection drops while that's 
happening.

The AMQP spec doesn't say a lot about the properties of transactions, 
and in particular, whether routing "happens" before or after tx.commit. 
  RabbitMQ routes before the tx.commit, mainly so that persistent 
messages will land on disk.

It would be well within the spec to *act* as though routing happened 
after tx.commit; e.g., the transaction wouldn't fail because your 
autodelete queue has gone away.  We'd also have to be careful of the 
second case, that failing to deliver the message didn't cause the 
tx.commit to fail.  That's probably a more useful semantics overall, anyway.

(We actually already have a bug for looking into this -- thanks for 
bringing back to our attention!)

> I see that 0.9.1 of the spec adds queue.unbind().  Is that the only
> way to avoid this problem, or is there another approach that we can
> take?

I don't see how queue.unbind would help -- would you explain?


Cheers,
Michael


More information about the rabbitmq-discuss mailing list