Closed flaper87 closed 7 years ago
How did you trigger this?
Here's a snippet to reproduce this, sorry for not adding it to the report:
from proton import Message
from proton.handlers import MessagingHandler
from proton.reactor import Container
class HelloWorld(MessagingHandler):
def __init__(self, server, address):
super(HelloWorld, self).__init__()
self.server = server
self.address = address
def on_start(self, event):
conn = event.container.connect(self.server, reconnect=False)
event.container.create_receiver(conn, self.address)
event.container.create_sender(conn, self.address)
def on_sendable(self, event):
event.sender.send(Message(body=u"Hello World", ttl=500))
event.sender.close()
def on_message(self, event):
print event.message.body
event.connection.close()
Container(HelloWorld("127.0.0.1:5672", "examples")).run()
I am seeing the same error when sending a message with the ttl set via qpip-proton (C++ binding).
According to the AMQP 1.0 spec, section 3.2.1, ttl should be encoded as milliseconds (which itself is an uint, 2.8.6).
Proton does indeed send milliseconds as uint, but the AMQP 1.0 plugin seems to expect a timestamp (which would be a 64-bit unsigned int).
The relevant code in rabbit_amqp1_0_message.erl:
to_expiration(undefined) ->
undefined;
to_expiration({timestamp, Num}) ->
list_to_binary(integer_to_list(Num)).
If I change timestamp to uint, everything works as expected for me.
This looks correct to me (although I am neither an erlang nor AMQP expert), but I didn't test other clients though.
RabbitMQ sends the following raw header for an AMQP 1.0 message with a ttl of 3599 seconds:
c0 0f 05 41 50 04 83 00 00 00 00 00 36 ea 98 41 40
Which decodes as:
c0 0f 05 constructor
41 durable: bool / true
50 04 priority: ubyte/ 04
83 00 00 00 00 00 36 ea 98 ttl: ms64 / 3599000 ms
41 first-acquirer: bool / true
40 delivery-count: null
0x83 is a timestamp encoded as ms64, fixed with of 8 bytes and representing milliseconds since the unix epoch - which doesn't match the encoded number of 3599000/0x36ea98 (3599s)
As far as what I could see in the code, qpid-proton seems to be lenient in parsing and simply skip the invalid ttl and interpret it as "no ttl"
The following is what proton sends (raw AMQP 1.0 Header):
d0 00 00 00 0f 00 00 00 05 41 50 04 70 00 36 ee 80 42 52 00 00 53 73
Which decodes as:
d0 00 00 00 0f 00 00 00 05 constructor: list32: 15 bytes/5 entries
41 durable: bool/true
50 04 priority: ubyte/4
70 00 36 ee 80 ttl: uint / 3600000
42 first-acquirer: bool / false
52 00 delivery-count: small-uint / 0
00 53 73 padding (???)
@kjnilsson perhaps this can be considered for backporting?
I'm using qpid-proton and I also observed this problem.
Are there any client side workarounds when creating/sending a message to RabbitMQ?
@dpocock until the next release you'd have to avoid using ttls.
Apparently, based on my very bad erlang knowledge (and some Erlangers help), there's a missing pattern in the
to_expiration
function.