3

I'm using pika's twisted protocol adapter. When I have have successfully handled the message I send an acknowledgement to RabbitMQ using this call:

channel.basic_ack(delivery_tag=delivery_tag) 

The basic_ack call seems to be firing asynchronously but it's not returning a deferred so I can't add a callback or errback. I've now run into a small problem because I want to wait for a certain message from the queue, process it and shutdown the reactor i.e.

channel.basic_ack(delivery_tag=delivery_tag)
reactor.stop()

Of course the reactor shuts down before the message is sent. I'm working around this by delaying the shutdown

channel.basic_ack(delivery_tag=delivery_tag)
reactor.callLater(5, reactor.stop)

But it seems like a pretty "hacky" way of doing it. I'd prefer to be able to do something like:

d = channel.basic_ack(...)
d.addBoth(lambda x: reactor.shutdown())

Am I missing something obvious here? Is it really not possible to chain a callback onto the end of an ack call?

  • When exactly do you want the callback to happen? – Jean-Paul Calderone Nov 16 '14 at 01:52
  • When the acknowledgment has be sent to RabbitMQ successfully, basically "thanks I've done the work you asked me to do, now I'm shutting down" –  Nov 16 '14 at 02:05
  • Does the RabbitMQ protocol include acks for acks? If not, how will you know when the ack has been sent to RabbitMQ successfully? – Jean-Paul Calderone Nov 16 '14 at 17:10
  • No it doesn't, but if I was using a blocking call I would block until execution resumed or an exception is raised. It seems that pika's twisted wrapper class returns deferreds for some calls but in the case of an ack call it just executes it async but doesn't return anything. I may have misunderstood how it works though, hence my question –  Nov 16 '14 at 20:20
  • I suspect that the cases where pika's APIs return a Deferred are cases where the RabbitMQ server returns a response. It's easy to see why it makes sense to return a Deferred in those cases - since the Deferred is the only way to get the data included in the server's response when the request/response API is asynchronous. It's also easy to see when the Deferred will fire in that case - it will fire when the response is received from the server. In cases where the server sends no response, it's less obvious when the Deferred would fire. The comparison to blocking code only gets us so far. – Jean-Paul Calderone Nov 16 '14 at 22:11
  • Yeah, that does make sense. I think my scenario is an edge case and is probably best handled as I'm currently doing it. I was just interested to know if I'd missed anything obvious. Thanks for you comments Jean-Paul –  Nov 16 '14 at 22:20
  • If the asynchronous API were to exactly replicate the functionality of the blocking API then the Deferred would fire when the data to write had been copied from the userspace buffer into the kernel buffer. Pika could probably offer this somehow (Twisted doesn't make it easy, though) but it's not an idiomatic way to build networking APIs with Twisted (hence the difficulty) because it doesn't reliably indicate that the peer has received the message (if the sending process crashes the message may still be lost, for example). – Jean-Paul Calderone Nov 16 '14 at 22:21

1 Answers1

0

So it seems the only option is to wait and hope the acknowledgement was sent successfully