jsr356-experts@websocket-spec.java.net

[jsr356-experts] Re: MessageHandler collection state changes and threading

From: Mark Thomas <mark_at_homeinbox.net>
Date: Tue, 09 Apr 2013 22:04:06 -0400

On 03/04/2013 14:05, Joakim Erdfelt wrote:
> Question on expectations of MessageHandler collection changes.
>
> Let me start by showing a scenario:
>
> 1. Endpoint is opened
> 2. Socket itself registers Session.addMessageHandler(new
> ChatMessageHandler()); // implements MessageHandler.Whole<String>
> 3. Incoming websocket frame. (op=TEXT, fin=false)
> 4. Implementation starts queuing up for whole message.
> 5. Incoming websocket frame. (op=CONTINUATION, fin=false)
> 6. Implementation appends frame for whole message.
> 7. Socket does Session.removeMessageHandler(chatMessageHandler);
> 8. Socket does Session.addMessageHandler(new EventMessageHandler()); //
> implements MessageHandler.Whole<String>
> 9. Incoming websocket frame. (op=CONTINUATION, fin=true)
> 10. Implementation appends frame for whole message.
> 11. Implementation notifies EventMessageHandler.onMessage(message); //
> Is this right?
>
> The implementation would need to make a judgement call at #4 to say that
> the incoming TEXT frame is for a MessageHandler.Whole<String> and start
> queueing up the message. (otherwise for MessageHandler.Partial, it can
> start notifying the MessageHandler immediately)
> However, when the implementation reaches step #11, the
> MessageHandler.Whole<String> has been swapped out.
>
> Question is, should the implementation lock the TEXT MessageHandler at
> step #3 (initial frame of message) till it is called at step #11 (last
> frame of message)?
> The PFD1 Javadoc for step #8 (Session.removeMessageHandler()) says that
> the remove should block until the handler is done processing and its no
> longer in use.
>
> In short, I'm just trying to put some rules around the
> Session.addMessageHandler and Session.removeMessageHandler, along with
> making the usage of provided MessageHandlers consistent in a threading
> scenario.
>
> One technique, would be to prevent altering the MessageHandler
> collection while in the middle of a websocket message. Only allowing
> changes between websocket messages.
> But this seems like a recipe for a bad time with threading / dispatching
> / locks / etc ...
>
> The technique Jetty has settled on, but we don't know if this is sane,
> is to pull from the MessageHandler collection at step #3 & 4 (initial
> incoming frame for the start of websocket message) and continue to use
> it for the rest of the message, making the MessageHandler collection
> itself not need any extra concurrency rules and eliminating the need to
> lock on step #7 and #8.
>
> I am also working with a scenario where the Session starts with a
> MessageHandler.Partial and then gets swapped out for a
> MessageHandler.Whole. This means that I'll be treating a
> MessageHandler.Partial with the same rules for and entire websocket
> message. Once you start a websocket message, you continue to use the
> same MessageHandler for the entire message.
>
> In our approach, the blocking requirement of
> Session.removeMessageHandler() is irrelevant. In our approach removing
> the MessageHandler is just an indication that future messages should not
> use this MessageHandler.
>
> Is this a sane approach?

I'm all for clarifying these sorts of edge cases sooner rather than
later. Your suggested approach seems reasonable to me.

It does mean we would need to change the Javadoc for
Session.removeMessageHandler()

Mark