benjamin-hodgson / asynqp

An AMQP library for asyncio
MIT License
84 stars 29 forks source link

AttributeError when publishing #7

Closed selaux closed 10 years ago

selaux commented 10 years ago

Im getting an error when publishing a message with the following code and i can't get behind the issue:

connection = yield from asynqp.connect(
     RABBITMQ_HOST,
     RABBITMQ_PORT,
     RABBITMQ_USERNAME,
     RABBITMQ_PASSWORD,
     RABBITMQ_VIRTUAL_HOST
)
channel = yield from self.connection.open_channel()
exchange = yield from self.channel.declare_exchange('home-automation', 'topic')
msg = asynqp.Message({'test_body': 'content'})
exchange.publish(msg, 'test.hello')

The trace of the error:

Exception in callback <bound method _SelectorSocketTransport._read_ready of <asyncio.selector_events._SelectorSocketTransport object at 0xb635bc70>>()
handle: Handle(<bound method _SelectorSocketTransport._read_ready of <asyncio.selector_events._SelectorSocketTransport object at 0xb635bc70>>, ())
Traceback (most recent call last):
  File "/home/pi/home-automation/venv/lib/python3.4/site-packages/asynqp/bases.py", line 28, in handle
    handler = getattr(self, 'handle_' + type(frame).__name__)
AttributeError: 'ChannelFrameHandler' object has no attribute 'handle_MethodFrame'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/python3.4/lib/python3.4/asyncio/events.py", line 39, in _run
    self._callback(*self._args)
  File "/opt/python3.4/lib/python3.4/asyncio/selector_events.py", line 473, in _read_ready
    self._protocol.data_received(data)
  File "/home/pi/home-automation/venv/lib/python3.4/site-packages/asynqp/protocol.py", line 42, in data_received
    self.dispatcher.dispatch(frame)
  File "/home/pi/home-automation/venv/lib/python3.4/site-packages/asynqp/protocol.py", line 80, in dispatch
    handler.handle(frame)
  File "/home/pi/home-automation/venv/lib/python3.4/site-packages/asynqp/channel.py", line 150, in handle
    super().handle(frame)
  File "/home/pi/home-automation/venv/lib/python3.4/site-packages/asynqp/bases.py", line 30, in handle
    handler = getattr(self, 'handle_' + type(frame.payload).__name__)
AttributeError: 'ChannelFrameHandler' object has no attribute 'handle_BasicReturn'

RabbitMQ Version: 3.3.5

I don't know what other information you need to trace this.

benjamin-hodgson commented 10 years ago

Hi, thanks a lot for the detailed bug report.

What's happened here is that the rabbitmq server was unable to deliver your message, so it's returned it to you using the "basic return" message. The exception happens because I haven't got around to implementing basic return yet. (This lib is still in 'alpha' mode!)

I need to think about the API before writing this code... I'll probably be able to get the feature done (and maybe fixing issue #2) next Tuesday or Wednesday. In the mean time I'm going to leave this issue open.

Hope that's all OK for you!

benjamin-hodgson commented 10 years ago

@selaux I've written a provisional API for returned messages. By default it'll throw an exception (so you'll still see "Future/Task exception was never retrieved") but you can now override this using channel.set_return_handler. This method accepts a function which will be called when the server returns an undeliverable message.

Can you try installing the latest code on the master branch and let me know whether this adequately addresses your issue?

Thanks, Benjamin

selaux commented 10 years ago

I will test it tonight and let you know.

selaux commented 10 years ago

Yeah :+1:, I can work with that solution, but couldn't it be possible so add publish-coroutine that waits until the response from rabbitmq is received? (or maybe I don't get the protocol :wink:)

benjamin-hodgson commented 10 years ago

Unfortunately that can't be done - when the message is delivered successfully there's no reply from the server. So the coroutine would be waiting forever :wink: