Description of problem: When a consumer sends modified outcome of a message with undeliverable-here=true and delivery-failed=false, the broker - sends the message to the same consumer again - increases delivery-count of the message First violates AMQP 1.0 spec: 3.4.5 Modified: "If the undeliverable-here is set, then any messages released MUST NOT be redelivered to the modifying link endpoint." Second is questionable per: "If the delivery-failed flag is set, any messages modified MUST have their delivery-count incremented." (that implies delivery-failed=false SHOULD NOT increase delivery-count) Please fix the first flaw and consider changing behaviour of the second one. Version-Release number of selected component (if applicable): qpid-cpp-server-0.34-5.el6.x86_64 How reproducible: 100% Steps to Reproduce: to be added Actual results: See Description (and future reproducer) Expected results: See Description (and future reproducer) Additional info: qpid/cpp/src/qpid/broker/amqp/Outgoing.cpp: .. case PN_MODIFIED: if (preAcquires()) queue->release(r.cursor, pn_disposition_is_failed(pn_delivery_remote(delivery))); //TODO: handle undeliverable-here and message-annotations outgoingMessageRejected();//TODO: not quite true... break; ..
I've committed a fix upstream that causes undeliverable-here messages to be rejected: https://svn.apache.org/r1715199. I believe this avoids any violation of the spec. If delivery-failed is false (and the message is not rejected) then the delivery count does not appear to get incremented as things stand.
Reproducer: #!/usr/bin/python import optparse from proton import Delivery, symbol from proton.handlers import MessagingHandler from proton.reactor import Container def dump(obj): for attr in dir(obj): print "obj.%s = %s" % (attr, getattr(obj, attr)) class Recv(MessagingHandler): def __init__(self, url, failed): super(Recv, self).__init__(auto_accept=False) self.url = url self.failed = failed def on_start(self, event): event.container.create_receiver(self.url) def on_message(self, event): print event._attrs event.delivery.local.failed = self.failed event.delivery.local.undeliverable = True event.delivery.update(Delivery.MODIFIED) event.delivery.settle() # event.connection.close() parser = optparse.OptionParser(usage="usage: %prog [options]") parser.add_option("-a", "--address", default="localhost:5672/examples", help="address from which messages are received (default %default)") parser.add_option("-f", "--failed", action="store_true", help="delivery-failed") opts, args = parser.parse_args() try: Container(Recv(opts.address, opts.failed != None)).run() except KeyboardInterrupt: pass 1) service qpidd restart; qpid-send -a "examples; {create:always}" -m1 2) python modified.py 3) service qpidd restart; qpid-send -a "examples; {create:always}" -m1 4) python modified.py -f Expected behaviour: 2) prints one message like: {'message': Message{priority=0, first_acquirer=1, user_id="", content_type="text/plain", properties={"sn"=1, "ts"=1448228051627021916}}} 4) prints the same Observed behaviour: 2) prints same message like: {'message': Message{priority=0, first_acquirer=1, user_id="", content_type="text/plain", properties={"sn"=1, "ts"=1448228301965840558}}} .. forever 4) prints messages like: {'message': Message{priority=0, first_acquirer=1, user_id="", content_type="text/plain", properties={"sn"=1, "ts"=1448228254722139242}}} {'message': Message{priority=0, delivery_count=1, user_id="", content_type="text/plain", properties={"sn"=1, "ts"=1448228254722139242}}} {'message': Message{priority=0, delivery_count=2, user_id="", content_type="text/plain", properties={"sn"=1, "ts"=1448228254722139242}}} .. forever
(In reply to Gordon Sim from comment #1) > I've committed a fix upstream that causes undeliverable-here messages to be > rejected: https://svn.apache.org/r1715199. I believe this avoids any > violation of the spec. Although it is not stated there that undeliverable-here=true MODIFIED messages should be offered to other consumers, I expect that is the intention behind the spec. But I agree implementing it would be a bigger task - every message would have to keep a list of consumers setting undeliverable-here in past.. I.e. I am not happy from the implementation but dont see much better. > > If delivery-failed is false (and the message is not rejected) then the > delivery count does not appear to get incremented as things stand. Agreed from my experiments, clarifying with original reporter their reproducer/scenario.
This bug was fixed upstream (QPID-6870, as much as we will fix it) as of 1.35.0. Thus it was part of the MRG release downstream when we rebased to qpid-cpp 1.35.0. So closing since it's now in MRG.