Thanks again for another update Gordon. Some responses inline below.


On 03/02/14 21:08, Gordon Sim wrote:
On 02/03/2014 07:53 PM, Fraser Adams wrote:
On 03/02/14 15:38, Gordon Sim wrote:
They should be set for outgoing messages as of 0.24[1]. What version
were you using?
I was actually using 0.27 off trunk built a couple of weeks ago.

Which properties didn't work for you using the x-amqp-* name?

I think that we may be speaking at cross purposes on this one, when you said "They should be set for outgoing messages as of 0.24[1]. What version were you using? " I had assumed that you were referring to the comments around the "to" being observed by the receiver if sent from AMQP 0.10 but not from AMQP 1.0 and the comment around that happening in the AMQP 0.10 -> AMQP 1.0 code. Re "Which properties didn't work for you using the x-amqp-* name" I'm not aware of any issue there (though I've not tried many) certainly it works fine for x-amqp-to as in the example:

./spout --connection-options {protocol:amqp1.0} -b localhost -P x-amqp-to=amqp://localhost/amq.fanout --content "Hello World" "amq.fanout"






[...]
The 0-10 to 1.0 conversion currently maps the 0-10 message-transfer's
'destination' onto to the 'to' field. At the time I did it it seemed
logical enough, but I'm happy to remove that if it is confusing (as it
probably is).
It's a difficult call, I personally suspect that it's potentially
confusing. When I was trying this stuff out I wasn't sure if it was
something that AMQP 0.10 qpid::messaging did or was an artefact of the
mapping. It's probably safest to expect it to be explicitly added like
it is on Messenger, might be worth a wider discussion though.

In translating from 0-10 to 1.0 it can't really be explicitly added, unless you mean as a special entry in the 0-10 application-properties? (On 1.0 the default is indeed to require iut to be explicitly set).

I think that you've misinterpreted what I was meaning by "explicitly added" here, what I was simply meaning was expecting x-amqp-to to be set by the producer. If as you say that on 1.0 the default is to require it to be explicitly set the perhaps it's not unreasonable to expect applications (even if still using 0.10 on the producer side) to actually set it (x-amqp-to will just look like an ordinary property to 0.10 won't it).

I'm kind of easy on this I guess as long as the pure 1.0 to 1.0 behaves in a consistent manner when compared to say Messenger then it's probably a coin toss as to what to do when translating.





[...]
I added the incoming and outgoing link entities as they seemed to be
useful when thinking in terms of the 1.0 model. The source and target
are as they appear in the attach received.
Yeah those seem to have potential, I stumbled across the "domain" and
"incoming"/"outgoing" stuff I've not had a chance to play yet but the
ability to establish links with arbitrary AMQP 1.0 containers seems
really cool. Is this stuff ultimately intended to replace the
"traditional" link/bridge federation model?

Listing the incoming and outgoing entities is useful even for a standalone broker. Creating them offers a mechanism similar to the links/bridges in 0-10.

Yeah I can see why listing the incoming/outgoing entities would be useful for a standalone broker - presumably being able to navigate from a subscription queue to a link would enable me to see say the filters/selectors and other properties of the link (I'd be really nice to be able to see what filters/selectors were present).

But my question was more about technical direction, as I say for AMQP 1.0 systems is this ultimately intended to become the primary way to enable federation? TBH from what I've seen it looks quite neat, but I'll need to play a bit more to compare and contrast that approach with "traditional" federation.




* Reply-to

The qpid::messaging library doesn't particularly restrict the value of
the reply-to in the message itself[4].

If it can be interpreted as of the form <name>/<subject>, then the
address object returned will have both the name and subject set to the
respective substrings. Otherwise the name will contain the full reply-to.

If the application takes that address and uses it directly as an
address for creating a sender, the name is used as the source or
target address for the link and if a subject is specified it will be
used to set a filter.

I believe a common usage will have reply-to simply contain a node name
(often for a temporary queue). That pattern, essentially the
client-server example, works against several brokers and also the
dispatch router[5]. It is also familiar from JMS.

However if some other specific scheme/format is used, the application
would responsible for interpreting the address and e.g. establishing
separate connections etc if that behaviour is desired.
I'll need to have more of a play with Reply-To but the thing I was
really trying to get at was that given the peer to peer model of AMQP
1.0 it is (presumably) possible to set a Reply-To to the complete unique
address of the sender (including host:port part) and the receiver could
presumably directly address the sender without necessarily returning via
intermediaries. That scenario seemed awkward for a connection oriented
paradigm such as qpid::messaging or JMS because the host:port part might
be an entirely different connection to the one it has used to connect to
say a broker.

With qpid::messaging you can set a reply-to of almost any form on a message as well as getting it off a received message.

However passing the reply-to directly back to createReceiver() will result in an attach being sent for a receiver link with the source set to the node name in the address. It can't sensibly do anything else.

If you want to use other schemes, such as something that identifies a different process to connect to or whatever, then the application needs to handle the reply to according to whatever scheme is in use.

So if I'm interpreting you correctly here; if say I'm a sender on localhost on port 5673 I might want to set a fully qualified reply to AMQP address of say:

amqp://localhost:5673/response

Now a consumer could in theory happily send a response directly to that address because of the peer to peer nature of AMQP 1.0, but I think what you are saying is that in qpid::messaging if such a ReplyTo was send there is no automagic mechanism given such an Address that if you pass it to createReceiver() it will cleverly create a Connection/Session. Similarly then I guess that if you got such an address on a |*getJMSReplyTo <http://docs.oracle.com/javaee/5/api/javax/jms/Message.html#getJMSReplyTo%28%29>*()| you wouldn't simply be able to do |*send <http://docs.oracle.com/javaee/5/api/javax/jms/MessageProducer.html#send%28javax.jms.Destination,%20javax.jms.Message%29>*(Destination <http://docs.oracle.com/javaee/5/api/javax/jms/Destination.html> destination, Message <http://docs.oracle.com/javaee/5/api/javax/jms/Message.html> message)| on a MessageProducer. So what you'd have to do would be to parse the ReplyTo to see if it had an amqp://<host>:<port> part and if it did create the necessary connection/session stuff and use the node name part for the actual qpid::messaging Address.

So that makes some level of sense, but that's what I was meaning when I said that this scenario (which seems quite reasonable given the peer to peer nature of AMQP 1.0) was slightly *awkward* for connection oriented APIs. Presumably if say Proton Messenger was the consumer you'd simply be able to take the ReplyTo in this case and use that as as the address when you do pn_message_set_address(message, address); So I think that there is some scope for confusion/complexity as to *exactly* what an address means as the interpretation is subtly different between connection oriented and message oriented paradigms.


I guess that if you're always using node names on the container that the consumer is connected to then everything is OK, but if not isn't there scope for things getting a bit interesting - surely a consumer is decoupled from a producer so it doesn't necessarily know how it has set its reply to (as a node or a fully qualified address).




[...]
* Shared subscriptions

The 'shared' subscription capability is described in the AMQP 1.0 readme.
Yeah I did notice it there, my problem was working out what the syntax I
needed to use was.

Note that it is a qpidd specific extension. At present the
subscription queue will be autodeleted unless you set the link to be
durable or reliable.
Ah I didn't realise that the reliable flag would help me. So would that
be something like reliability:|||at-least-once| in the link properties?

Yes

Just to confirm that doing:

./drain --connection-options {protocol:amqp1.0} -b localhost -f \
"amq.fanout; {node: {capabilities: [shared]}, link: {name: test-link, reliability: at-least-once}}"

Does indeed set autoDelete to false on the subscription queue.

However that raises another question in my mind (sorry for being a pain in the butt!!!)

In AMQP 0.10 as far as I was aware the default reliability was actually at-least-once, or at any rate I don't believe that the default was unreliable. The reason I'm thinking this was because I always had to explicitly do link: {reliability: unreliable} for a couple of use cases where I didn't want my consumers to have to acknowledge the messages.

This stuff above *seems* to point to the default reliability in AMQP 1.0 as being unreliable - is that observation correct, if so there's clearly an inconsistency between AMQP 0.10 and 1.0




So are you saying that other AMQP 1.0 brokers generally don't support
shared subscriptions? TBH that seems unfortunate I know that I find them
incredibly useful to distribute workload between physical consumers.

They do likely support them, but they either won't expose that capability over AMQP 1.0 yet or they will do so in a different way (I haven't seen any other approach documented or I would have attempted to follow it).
Just because it's not documented doesn't mean it doesn't exist ;-p
If that were the case........





Supporting an expiry policy of 'never' should be possible as well.
I'll update the test to note the convention around queue name.
What I was getting at in that section of my post was "I couldn't see
anything in the qpid::messaging code related to expiry" in other words
there was no reference to pn_terminus_set_expiry_policy so (I think)
it's additional code that's needed - have I missed something?

Right, there is no support as yet for controlling the expiration policy (right now link scope is assumed). Adding 'never' should not be difficult.
Cool, I guess expiry policy is probably the most *obvious* way do do this from the spec (well to me anyway, which probably doesn't count for much).





[...]
So that's slightly worrying I hadn't clocked that. What I'm not clear
about then is how I'd go about mapping the scenario I had with:

x-bindings: [{exchange: 'amq.match', queue: 'testqueue', key: 'key1',
arguments: {x-match: all, data-service: amqp-delivery, item-owner:
fadams}}, {exchange: 'amq.match', queue: 'testqueue', key: 'key2',
arguments: {x-match: all, data-service: http-delivery, item-owner:
fadams}}]

In this AMQP 0.10 case I've got two separate bindings added between
amq.match and "testqueue" so messages will be delivered if either of
them match.

I (naively) thought that multiple filters was the way (though on
reflection I can see that all filters must match - how else would my
topic plus selector example work the way it did d'Oh).

Can you think of a way how the use case I've suggested might be
supported (aside from selectors - they are cool, but it'd be good to be
able to replicate the legacy headers stuff completely - especially for
migration/integration purposes).

Not really, I guess a new filter type of some kind would be one path. However I do think that using selectors is better and should work well even for migration/integration. You could have a headers filter that matched everything (e.g. just amq.match:any) and then specify the rest of the matching logic as a selector and your receiver would behave the same as if it had two headers bindings.

I was thinking about this. So I agree that ultimately using selectors is better (and I did do exactly what you say here in my "Bringing it all together" example albeit being even more fancy with the addition of topic filtering too). So don't get me wrong I really do like message selectors, but I also think that the legacy headers stuff really ought to be able to support everything the current AMQP 0.10 model can, especially as it's *nearly* there. So at the moment the headers stuff with a single x-bindings value looks like this.

./drain --connection-options {protocol:amqp1.0} -b localhost -f \
"amq.match; {link: {name: test-link, filter: {name: key, descriptor: 'apache.org:legacy-amqp-headers-binding:map', value: {x-match: all, data-service: amqp-delivery, item-owner: fadams}}}}"

Looking in AddressHelper.cpp from what I can make out filters get added in AddressHelper::configure and in there there's a block that iterates through the filters and for each calls write(filter, i->value);

Unless I'm mistaken that value is a Variant::

Now in the example above it is clearly a Map, but I'm wondering about the possibility of extending what gets accepted for
apache.org:legacy-amqp-headers-binding to either:
a) Include another variant of this such as apache.org:legacy-amqp-headers-binding:list such that you could have a subscription like:

./drain --connection-options {protocol:amqp1.0} -b localhost -f \
"amq.match; {link: {name: test-link, filter: {name: headers, descriptor: 'apache.org:legacy-amqp-headers-binding:list', value: [{x-match: all, data-service: amqp-delivery, item-owner: fadams}, {x-match: all, data-service: http-delivery, item-owner: fadams}]}}}"

In other words the value part is a list of maps. Alternatively

b) For the apache.org:legacy-amqp-headers-binding:map use an x- property (perhaps even x-bindings) whose value is a list e.g. something like:

./drain --connection-options {protocol:amqp1.0} -b localhost -f \
"amq.match; {link: {name: test-link, filter: {name: headers, descriptor: 'apache.org:legacy-amqp-headers-binding:map', value: {x-bindings: [{x-match: all, data-service: amqp-delivery, item-owner: fadams}, {x-match: all, data-service: http-delivery, item-owner: fadams}]}}}}"

You could possibly even use the original x-bindings as the property of the filter's "value" Map though the exchange and queue parts wouldn't make sense, but it would give a handy place for the key - so, for example:


./drain --connection-options {protocol:amqp1.0} -b localhost -f \
"amq.match; {link: {name: test-link, filter: {name: headers, descriptor: 'apache.org:legacy-amqp-headers-binding:map', value: {x-bindings: [{key: 'key1', arguments: {x-match: all, data-service: amqp-delivery, item-owner: fadams}}, { key: 'key2', arguments: {x-match: all, data-service: http-delivery, item-owner:
fadams}}]}}}}"

So as far as I can see that technically doesn't change the semantic of the filter as the type is a map, the existing approach for a single binding should still work but by interpreting x-bindings you'd essentially have the ability to do exactly what you can currently do, which seems kind of cool.

I've no idea how much work this would be though - as I say, sorry for being a pain :-)





[...]
However we could probably look at ways to (optionally?) make this more
lenient. It certainly is also something that should be highlighted
more prominently in documentation somehow.
It would be *really really good* to be able to make this more lenient
(would quoted field names be a possibility e.g.
'data-service'='amqp-delivery')?

I've not looked at the parsing code, but I would think something like that should be possible and I agree that it would be useful since AMQP itself places no restrictions on property names.

Pleeeeeaaaaaassssseee :-)

Seriously, finding a way to work through the hyphen issue would be awesome.





[...]
I believe the selector filters are supported by a number of brokers
outside Qpid (ActiveMQ, HornetQ, SwiftMQ).
That's useful to know, have you tried many interoperability scenarios?

I've successfully tried selectors against ActiveMQ. The only quirk is that it doesn't actually recognise the filters descriptor, but just recognises the filter name as used by the current qpid JMS over 1.0 client. SO the selector shorthand doesn't work, but a fully specified filter will.

I'm not quite sure I understand what you mean here, as I understand it "selector: " is a qpid shortand, but I *thought* that over the wire that got translated to a filter with a descriptor apache.org:selector-filter:string so I *thought*

selector: \"data-service='amqp-delivery' and item-owner='fadams'\"}

was shorthand for

filter: {name: selector, descriptor: 'apache.org:selector-filter:string', value: \"data-service='amqp-delivery' and item-owner='fadams'\"}

So are you saying that it accepts

filter: {name: selector, descriptor: 'x-filter-jms-selector', value: \"data-service='amqp-delivery' and item-owner='fadams'\"}

Or simply link : {x-filter-jms-selector: \"data-service='amqp-delivery' and item-owner='fadams'\"}

I *thought* that in AMQP 0.10 it went something like:

{link:{x-subscribe:{arguments:{x-filter-jms-selector:\"data-service='amqp-delivery' and item-owner='fadams'\"}}}}

But that won't work in AMQP 1.0 because the x-subscribe is forbidden.


Actually that reminds me - so in JMS I could specify selectors on the link as with qpid::messaging, but the JMS API also allows selectors to be specified from the Session |*createConsumer <http://docs.oracle.com/javaee/5/api/javax/jms/Session.html#createConsumer%28javax.jms.Destination,%20java.lang.String%29>*(Destination <http://docs.oracle.com/javaee/5/api/javax/jms/Destination.html> destination, String <http://java.sun.com/j2se/1.5/docs/api/java/lang/String.html> messageSelector)|

I probably shouldn't as this, but..... are you suggesting that at the moment with Qpid JMS specifying it from the Session will result in a different syntax on the link attach? If so will they both work with the Qpid brokers?

Sorry for all the crazy questions, there's a lot of subtlety in all of this.

Cheers,
Frase






Reply via email to