You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Rob Godfrey <ro...@gmail.com> on 2014/08/25 12:47:33 UTC

Questions on Addresses

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).

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 ).  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.  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).  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?

-- Rob


[1] https://issues.apache.org/jira/browse/QPID-6037

[2]  https://issues.apache.org/jira/browse/QPID-6040

Re: Questions on Addresses

Posted by Rob Godfrey <ro...@gmail.com>.
On 26 August 2014 13:58, Gordon Sim <gs...@redhat.com> wrote:

> On 08/26/2014 11:15 AM, Rob Godfrey wrote:
>
>> On 26 August 2014 11:23, Gordon Sim <gs...@redhat.com> wrote:
>>
>>> 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?
>>
>
> No, I just meant specifying that the node should be treated like a queue
> as you say.
>
>
>  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)?
>>
>
> The passive declare is mostly there for the send side, to try and give you
> an error rather than having messages silently dropped. Having it on the
> receive side is mostly because the two cases share common code (and because
> at one time it was considered 'good practice' in AMQP to passively declare
> queues before using them).
>
> I don't think it would be hugely difficult to change this if anyone needed
> it.
>
> That said if the queues to subscribe to are actually conveyed in the
> subscribe arguments, and the node name was some 'special' node, a bit like
> the default exchange, then perhaps you could just define a long form name -
> e.g. qpid.nameless - and have passive declare of the return true for that
> on name(?).
>
>
>
Yes - I'm not necessarily averse to that, more that I don't want to have to
also fake it in QueueQuery, ExchangeBound, etc... it'd be nice if there was
a way to turn off the checking in the client(s) such that if you have an
intermediary that just magics up addresses on demand then it can do so
while not actually telling lies in response to other queries.  Similarly
there may be nodes like the AMQP management node that are not really queues
and not really exchanges, but you should be able to address them through
AMQP 0-x.


>  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.
>>
>
> That is more or less what the c++ client does. If you tell it the node is
> a queue, it does not try to resolve it or query any further information
> about it, it just proceeds on the assumption that it is a queue. The only
> problematic part is that that assumption causes it to passively declare the
> queue before subscribing.
>
> I think the 'ideal' fix for 0-10 JMS, assuming it's feasible on the code
> side without huge upheaval, would be to do something similar, and skip
> resolution/querying if the type is given.
>
>
>
Yeah - my work in progress does exactly this (basically put a break; at the
end of each of the case statements in the switch I pasted previously).  It
just means that some of the tests "fail" because they are testing exactly
this behaviour.

If no-one else strenuously objects to this change in the behaviour when an
address is not defined with assert, then I shall commit this.

-- Rob


>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
> For additional commands, e-mail: users-help@qpid.apache.org
>
>

Re: Questions on Addresses

Posted by Gordon Sim <gs...@redhat.com>.
On 08/26/2014 11:15 AM, Rob Godfrey wrote:
> On 26 August 2014 11:23, Gordon Sim <gs...@redhat.com> wrote:
>> 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?

No, I just meant specifying that the node should be treated like a queue 
as you say.

> 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)?

The passive declare is mostly there for the send side, to try and give 
you an error rather than having messages silently dropped. Having it on 
the receive side is mostly because the two cases share common code (and 
because at one time it was considered 'good practice' in AMQP to 
passively declare queues before using them).

I don't think it would be hugely difficult to change this if anyone 
needed it.

That said if the queues to subscribe to are actually conveyed in the 
subscribe arguments, and the node name was some 'special' node, a bit 
like the default exchange, then perhaps you could just define a long 
form name - e.g. qpid.nameless - and have passive declare of the return 
true for that on name(?).

> 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.

That is more or less what the c++ client does. If you tell it the node 
is a queue, it does not try to resolve it or query any further 
information about it, it just proceeds on the assumption that it is a 
queue. The only problematic part is that that assumption causes it to 
passively declare the queue before subscribing.

I think the 'ideal' fix for 0-10 JMS, assuming it's feasible on the code 
side without huge upheaval, would be to do something similar, and skip 
resolution/querying if the type is given.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Re: Questions on Addresses

Posted by Rob Godfrey <ro...@gmail.com>.
Hi Gordon,

thanks for your, as ever, very helpful response

On 26 August 2014 11:23, Gordon Sim <gs...@redhat.com> 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

Re: Questions on Addresses

Posted by Gordon Sim <gs...@redhat.com>.
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.

> 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}}

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).

>  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?

Would it ever make sense to create a sender to such a pseudo-node? Or 
would the sender always be to an exchange?

> 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).

> -- Rob
>
>
> [1] https://issues.apache.org/jira/browse/QPID-6037
>
> [2]  https://issues.apache.org/jira/browse/QPID-6040
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org