Polyconseil / aioamqp

AMQP implementation using asyncio
Other
280 stars 88 forks source link

Error when using "basic_cancel" #126

Closed nhumrich closed 7 years ago

nhumrich commented 7 years ago

Everytime I try to use basic_cancel I get an error that says "501 Frame Error"

aioamqp.exceptions.ChannelClosed: (501, 'FRAME_ERROR - cannot decode <<1,0>>')

Here is an example program:

import asyncio

import aioamqp

channel = None
async def run():
    global channel
    t, p = await aioamqp.connect()
    channel = await p.channel()
    await channel.queue_declare(queue_name='test')
    await channel.basic_qos(prefetch_count=1, prefetch_size=0)
    return await channel.basic_consume(handle, queue_name='test', no_ack=True)

async def handle(channel, body, envelope, properties):
    print('do stuff')

async def close(consumer_id):
    await channel.basic_cancel(consumer_id)

loop = asyncio.get_event_loop()
consumer_id = loop.run_until_complete(run())
loop.run_until_complete(close(consumer_id))

Running on Python 3.5.2 gives me:

Server closed connection: FRAME_ERROR - cannot decode <<1,0>>, code=501, class_id=60, method_id=30
Traceback (most recent call last):
  File "/home/nhumrich/test3.py", line 22, in <module>
    loop.run_until_complete(close(consumer_id))
  File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "/home/nhumrich/test3.py", line 18, in close
    await channel.basic_cancel(consumer_id)
  File "/usr/lib/python3.5/site-packages/aioamqp/channel.py", line 678, in basic_cancel
    'basic_cancel', frame, request, no_wait=no_wait, timeout=timeout))
  File "/usr/lib/python3.5/site-packages/aioamqp/channel.py", line 201, in _write_frame_awaiting_response
    return (yield from f)
  File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
aioamqp.exceptions.ChannelClosed: (501, 'FRAME_ERROR - cannot decode <<1,0>>')
nhumrich commented 7 years ago

Now I see that consumer_tag returned is just a dictionary with a key, that has to be pulled out of the dict.

result = loop.run_until_complete(run())
consumer_id = result['consumer_tag']

So this issue is now moreso the fact that either a) the return to basic_consume should just be a string, or b) that basic_cancel should except the dict, or c) should give a much better error for invalid input.

dzen commented 7 years ago

Hello Nick,

This could be an improvement in the API for sure.

RemiCardona commented 7 years ago

Adding a reference to #118 to think about this further.

But closing as there's no actual bug here (just a weird API from us).