Hi All, I wanted to re-raise Ted's suggestion regarding the need for a better Messenger API for handling reply-to's.
I've could've used this recently while designing a "echo" stress test for Messenger. For my client, I have two requirements: 1) I don't want to have to assign a publicly visible address to the client in order to receive replies. 2) I only want a reply for particular messages. I think these two requirements are common enough to merit some Messenger API lovin'. In that context, Ted's API recommendation makes my life as the client writer easier: It doesn't require me to obtain a reply-to value up-front (ie. before calling pn_messenger_put()), and it doesn't cause every message to be sent with a reply-to (which, I believe is the current case - messenger always adds a reply-to if not set). I think there's value in Ted's proposal, but I'd recommend a slight modification to it: rather than mark the message directly, instead indicate to Messenger that a particular message needs its reply-to set correctly prior to transmitting it. For example, we could add a flag to pn_messenger_put(): msg = pn_message(); pn_message_set_address( msg, "peer's remote address" ); .... set message contents, cid, etc ... pn_messenger_put( messenger, msg, PN_SET_REPLY_TO ); Setting the PN_SET_REPLY_TO would cause Messenger to set the reply-to properly prior to sending, or signal an error if unable to do so (reported via a tracker, as usual). This API change would satisfy my two requirements, while keeping the whole address management stuff out of my client. Thoughts? -K ----- Original Message ----- > From: "Rafael Schloming" <r...@alum.mit.edu> > To: proton@qpid.apache.org > Sent: Friday, January 18, 2013 9:13:34 AM > Subject: Re: Proton Messenger and the Request/Response pattern > > Gordon makes some good points. I'd like to add that I think > historically a > big part of the hassle isn't actually necessarily solely the API but > also > having to configure and manage the intermediary, and I think we need > to > look there as well if we want to simplify the overall pattern. > > It's also worth remembering that there are significant performance > benefits > to keeping Message as a pure value object (i.e. a content holder) > that can > be reused many times even across multiple Messengers. Some of the > suggestions really stray from this pattern. If I recall correctly, I > think > we said in prior threads that we wanted to maintain the notion of > Message > being a reusable content holder as an architectural invariant. > Perhaps it's > worth re-examining what we could do for request/response while > keeping this > invariant in mind. > > --Rafael > > On Fri, Jan 18, 2013 at 6:24 AM, Gordon Sim <g...@redhat.com> wrote: > > > On 01/02/2013 07:14 PM, Ted Ross wrote: > > > >> I'd like to start a discussion on how, from an API perspective, > >> applications can use the request/response pattern. If we get this > >> right, we will remove a significant barrier to adoption of AMQP. > >> > >> Middleware messaging systems typically do a poor job of supporting > >> this > >> pattern. The Qpid APIs are quite lacking in this regard > >> (requester > >> creates and subscribes to a temporary queue with a _unique_ name > >> and > >> places this name in the reply-to field). > >> > >> Proton Messenger supports request/reply (see > >> examples/messenger/$LANG/{**client,server}) as follows: > >> > >> The requester (client) has to put _something_ into the request > >> message's > >> reply_to field. It also sets the correlation_id field if it needs > >> to > >> dispatch multiple responses. The responder (server) must copy the > >> request message's reply_to field to the response message's address > >> field > >> and also copy the correlation_id. > >> > >> This API is good for the case where the client wants the response > >> to go > >> to a third party. In this case the reply_to is well understood to > >> be > >> the address of the third party receiver. However in the more > >> common > >> case where the response is intended to come back to the client, > >> it's not > >> clear at all what to put in the reply_to field. > >> > >> I propose that we allow the client to simply say > >> > >> request_msg.reply_expected(**cid) > >> > > > > A message has no association with a messenger (until it is put onto > > the > > messengers outgoing queue at least). It is not clear how a method > > on > > message would therefore be in any better position to determine the > > reply-address to use. > > > > At present, if a message on the outgoing queue has no reply-to set, > > then > > the messenger will automatically set the reply-to to be an address > > corresponding to itself. > > > > You can also use the (in my view slightly clumsy) syntax ~/xyz, > > which will > > be 'munged' into a form that prepends the messengers name to form a > > full > > address. This form I presume would be used if you want to > > distinguish > > different categories of replies. > > > > I'm not exactly enamoured with this, but it does seem at least to > > address > > the key concern expressed here, namely what to put in the reply-to > > for the > > simple case. (The answer being, nothing!) > > > > > > (I added the correlation_id argument because it's almost always > > going to > >> be needed). Further, the server could use > >> > >> reply_msg.in_reply_to(request_**msg) > >> > >> which would take care of the addresses and the correlation_id. It > >> also > >> provides a place to report an error if a request cannot be replied > >> to > >> (absent or invalid reply_to address) rather than force each server > >> implementer to code this check. > >> > > > > This is really just a short hand for: > > > > response.address = request.reply_to > > response.correlation_id = request.correlation_id > > > > plus some code or exception indicating whether the address has been > > set. I > > have no objection to such a utility, though I'm not entirely > > convinced that > > a method on message is the best place. It also seems of fairly > > marginal > > benefit rather than removing a 'significant barrier to adoption'. > > > > Have you seen the JMS solution to simplifying the request-response > > pattern? There it is done by specifying a distinct class that uses > > a > > supplied session and destination and provides a request() method > > that takes > > a request message as input and blocks until it can return the > > response > > message. (See http://docs.oracle.com/javaee/**1.4/api/javax/jms/** > > QueueRequestor.html<http://docs.oracle.com/javaee/1.4/api/javax/jms/QueueRequestor.html>). > > Details of creating temporary response queues etc are hidden behind > > this. I > > like that general approach as it layers the functionality cleanly > > on top of > > the more flexible base, and would also allow different > > configurations or > > conventions to be used. > > > > --Gordon. > > > > > -- -K