ask / carrot

AMQP Messaging Framework for Python (discontinued; Use Kombu instead)
http://ask.github.com/carrot/
BSD 3-Clause "New" or "Revised" License
197 stars 34 forks source link

No exception raised when mandatory=True and message cannot be routed #16

Open ltucker opened 15 years ago

ltucker commented 15 years ago

The documentation for the mandatory parameter of publisher.send states:

"If set, the message has mandatory routing. By default the message is silently dropped by the server if it can’t be routed to a queue. However - If the message is mandatory, an exception will be raised instead."

At least for the pyamqplib backend, no exception appears to be raised when the message cannot be routed to a queue. This is possibly more of an issue with an underlying driver or a documentation bug.

ask commented 15 years ago

This is actually a combination of several things, first this discussion: http://www.nabble.com/Channel-Cost-td21678526.html shows that in amqplib you have to close the channel to receive the error, so this is definitely a bug. But while testing I could only get it to raise an error if the exchange is not declared, no queues being bound to it didn't seem to affect the outcome. I'm investigating if this is a documentation bug in amqplib or if it's something else. Good catch!

alexluke commented 14 years ago

Any word on a fix for this?

jdnier commented 14 years ago

I would like to use this feature also...but I can't. Please fix. :)

ask commented 14 years ago

Actually, this doesn't work in amqplib either. It's not that easy to fix, because how do you know if it was delivered or not? Then you have to wait for a reply right, and you have no idea when that reply will come, so a synchronous solution is not as straightforward.

What I could implement is an immediate_timeout argument, which will block the publish call, and fail if a valid response hasn't been received within the timeout. This has obvious drawbacks, one being that you usually want publish to be asynchronous, not blocking. I'm not sure if there's anyone who even want this behavior.

The other solution would be to have an error_callback argument, which if set opens up another thread waiting for the reply. Instead of opening 1000 threads for 1000 messages, there could be a single thread running, responsible for handling responses for all 1000 messages. But I'm not sure this is doable, as py-amqplib does not support threading. Maybe there's a workaround though.

I know you guys want this, just wanted to let you know that at least I'm thinking about it :)

jdnier commented 14 years ago

The rabbitmq (Java) api guide explains a method for clients here (not sure if py-amqplib can do similar):

http://www.rabbitmq.com/api-guide.html#returning

"If a message is published with the "mandatory" or "immediate" flags set, but cannot be delivered, the broker will return it to the sending client (via a AMQP.Basic.Return command).

To be notified of such returns, clients can implement the ReturnListener interface and calling Channel.setReturnListener. If the client has not configured a return listener for a particular channel, then the associated returned messages will be silently dropped."

In the mean time, how about updating the docs to say the mandatory and immediate parameters are not yet implemented?

Thanks.