Hi Gordon, thanks for your, as ever, very helpful response
On 26 August 2014 11:23, Gordon Sim <[email protected]> wrote: > > On 08/25/2014 11:47 AM, Rob Godfrey wrote: >> >> While I was working on adding addressing support to the JMS 0-9-1 client >> [1] and looking at how I might implement a subscription where the >> subscription was to a set of queues (rather than a single queue) [2], I >> came across a couple of issues with the address implementation that I think >> I should probably discuss before I go ahead an "fix" them. >> >> Firstly the addressing syntax definition in >> http://qpid.apache.org/releases/qpid-trunk/programming/book/section-addresses.html#section-address-string-bnf >> defines the following: >> >> x-subscribe: { ... <subscribe-overrides> ... } >> >> However the JMS client looks for x-subscribes (note the plural). I presume >> this is just a mistake and should be corrected (though probably allowing >> the pluralised version for backward compatibility). > > > Yes, in python and c++ it is x-subscribe, singular. OK - it's a trivial enough change to add the correct name and preserve the old name in the interests of backwards compatibility > > > >> Secondly I would think that an address which explicitly or implicitly >> defines its assertion policy to be "never" should not fail in the act of >> creation if the node does not exist (otherwise what is the point of assert: >> never ). > > > In c++ and python the assertions are used to verify specific aspects of the node (e.g. to ensure it is a queue or that it is durable or is an lvq etc) rather than the existence of the node. > > Establishing a link to or from a node that does not exist will always fail (unless that node is to be created on demand). > > >> However it seems that the JMS client always explicitly tests for >> the presence of either a queue or an exchange and if it finds neither (even >> if the policy is assert" never) it fails. > > > The reason for the test is that in 0-10, how you establish sender and receivers depends on whether the node in question is an exchange or a queue. In c++ at least, you can skip the querying by simply telling the client what node type it is, e.g. > > my-queue; {node:{type:queue}} > > or > > my-exchange; {node:{type:topic}} > Yes - the issue in the JMS client is that even if you explicitly give the type, and explicit request no asserts, the definition of the address fails - see this code at line 685 of AMQSession.java (this code is called on the creation of the address, rather than only when a sender or receiver is created): int type = resolveAddressType(dest); switch (type) { case AMQDestination.QUEUE_TYPE: { if(createNode) { setLegacyFieldsForQueueType(dest); handleQueueNodeCreation(dest,noLocal); break; } else if (isQueueExist(dest,assertNode)) { setLegacyFieldsForQueueType(dest); break; } } case AMQDestination.TOPIC_TYPE: { if(createNode) { setLegacyFieldsForTopicType(dest); verifySubject(dest); handleExchangeNodeCreation(dest); break; } else if (isExchangeExist(dest,assertNode)) { setLegacyFieldsForTopicType(dest); verifySubject(dest); break; } } default: throw new AMQException( "The name '" + dest.getAddressName() + "' supplied in the address doesn't resolve to an exchange or a queue"); } Note that the node type of the address is resolved (if possible)... if it is found to be a queue but the definition isn't "create" or the queue doesn't exist it then drops into the TOPIC_TYPE case (there's no break if you don't match one of the two branches of the if)... if the address then doesn't match one of the two branches of the TOPIC_TYPE case then an exception is thrown. Thus if you define an address like foo ; { node: { type: queue } } the code will will drop through all the conditions (unless a queue or, more bizarrely an exchange, with the name foo is found)... and an exception will be thrown. Since the address doesn't ask for any asserts I think this is wrong (it also seems wrong that an address explicitly defined as a queue will be happy if there is an exchange found with the given name... but that's a different issue). Having it fail at the time a subscription request is made is fine... (the queue may or may not have been created in the meantime). > The c++ client however will always issue a 'declare' (with passive=true) before creating either a sender or receiver. This could be relaxed on the receiver side since the subscribe would fail anyway if the queue didn't exist (at present the check is on a common code path). > Yes - as I've currently defined my mutli-queue consumers in the Java Broker this check would need to be relaxed to work with those clients. I guess I could allow the passive declare to succeed, but I'm reluctant to have to present things as queues that aren't really queues (would queue query have to work as well... and what about testing to see if the name is bound to the default exchange - a technique the java client uses to establish queue existence in some paths). As the Java broker moves more towards a 1.0 model with a 0-x front end stuck on this will become more of an issue. > > >> Moreover there are tests >> checking this behaviour. I would like to change this behaviour also, as it >> prevents the creation of subscriptions to pseudo-nodes which are not queues >> or exchanges (for instance the multi queue subscription case). > > > So from an 0-10 perspective, for a receiver at least this pseudo-node is 'like' a queue? I.e. you can issue a message-subscribe to it with the name of the pseudo-node in the queue field? > Yes - the most obvious thing (and also something compatible with what 1.0 is doing) is to imagine a "no name address" (the anonymous relay in 1.0 speak) where the arguments on the subscription determine the messages that will be sent. In my prototype at the moment the code will actually just accept any address for the queue if it doesn't exist as a queue and the argument for the subscription is present. I'd like to change this to only be the no-name address, but in the 0-9-1 case this seems to somehow become the null address when it arrives at the broker - which has a particular meaning in 0-9-1 (that you should use the last declared queue or something). > Would it ever make sense to create a sender to such a pseudo-node? Or would the sender always be to an exchange? > I'm not planning on building an analogue for sending right now... though it sort of makes sense as a concept (you'd basically be constructing an on-the-fly fanout exchange with bindings to the queues specified). I'd like to try to bring this in line with the AMQP 1.0 addressing work where we are also starting to talk about address patterns, compound addresses ( <address_1> ; <address_2> ; ... ; <address_n> ) etc. > >> Clearly the >> act of attempting to subscribe to something the broker cannot resolve will >> still result in an error on the broker side, which seems to me the expected >> behaviour of assert: never. >> >> Thoughts? > > > I'd suggest using an explicit type to indicate which 0-10 commands should be issued when creating a receiver (and/or a sender). You may additionally need to avoid declaring the queue if that is not valid for these pseudo-nodes). > An explicit type on which element in the address. Obviously you need to explicitly need to state that the address should be treated as a queue node... but are you thinking of something else? If assert is false, and the type of the node is explicitly given, and creation is not requested, what is the rationale for declaring the queue before attempting subscription (both will result in a similar sort of error, won't they)? I'd certainly agree that if assert is false, or create is true, or the type isn't made explicit in the address string then you should expect that query or declare commands would be issued... But I'd think that if you provide an address that is basically saying "connect to this, don't check it, just do it - I've given you all the information you need" then we should do just that. -- Rob
