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

Reply via email to