celery / kombu

Messaging library for Python.
http://kombu.readthedocs.org/
BSD 3-Clause "New" or "Revised" License
2.89k stars 930 forks source link

Deserialize exception when message is empty #74

Closed kryskool closed 13 years ago

kryskool commented 13 years ago

I use kombu 1.4.1 with RabbitMQ

When message is send with an empty size, the default serialiser json return an exception. No problem to catch it, but we cannot ACK that we receive the message, and it was block in the Queue, and the purge cannot perform, because we may have some legitimate messages.

Traceback (most recent call last): File "receipt_diffusion3.py", line 53, in connection.drain_events() File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/connection.py", line 175, in drain_events return self.transport.drain_events(self.connection, kwargs) File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/transport/pyamqplib.py", line 238, in drain_events return connection.drain_events(kwargs) File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/transport/pyamqplib.py", line 57, in drain_events return self.wait_multi(self.channels.values(), timeout=timeout) File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/transport/pyamqplib.py", line 84, in wait_multi return amqp_method(channel, args, content) File "/home/alncchau/.local/lib/python2.6/site-packages/amqplib-1.0.2-py2.6.egg/amqplib/client_0_8/channel.py", line 2060, in _basic_deliver func(msg) File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/messaging.py", line 446, in _receive_callback decoded = message.payload File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/transport/base.py", line 159, in payload self._decoded_cache = self.decode() File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/transport/base.py", line 148, in decode self.content_encoding) File "/home/alncchau/.local/lib/python2.6/site-packages/kombu-1.4.1-py2.6.egg/kombu/serialization.py", line 149, in decode return decoder(data) File "/home/alncchau/.local/lib/python2.6/site-packages/anyjson-0.3.1-py2.6.egg/anyjson/init.py", line 130, in deserialize = lambda value: implementation.deserialize(value) File "/home/alncchau/.local/lib/python2.6/site-packages/anyjson-0.3.1-py2.6.egg/anyjson/init.py", line 99, in deserialize raise ValueError(*exc.args) ValueError: No JSON object could be decoded: line 1 column 0 (char 0)

I think, the good method to treat an empty message (when header containt json, pickle, yaml) is to return None type

I have fix this issue in my branch and push it quickly (see below output come from the sample example)

Received message: None -> properties: { 'content_encoding': u'utf-8', 'content_type': u'application/json', 'message_id': u'f7e16ee2-fb3d-11e0-ab83-0010c0a8976f'} -> delivery_info: { 'channel': <kombu.transport.pyamqplib.Channel object at 0xa54266c>, 'consumer_tag': u'1', 'delivery_tag': 1, 'exchange': u'eshop.ezpublish.output', 'redelivered': True, 'routing_key': u'partner.retrieve'}

Regards,

kryskool commented 13 years ago

I found another issue with my previous patch, when deserialization failed, it always return None,

I prefer to check if len(data) == 0 and return None, otherwize raise an error, and call the callback on_decode_error.