On 03/11/2012 00:36, Scott Ferguson wrote:
> On 11/2/12 4:59 PM, Danny Coward wrote:
>> Hi folks,
>>
>> Another question that has come up as people look at the API and
>> implement it is the issue of precedence when an endpoint has multiple
>> MessageHandlers. I wrote up a little proposal that seeks to define how
>> the container is supposed to select which of potentially numerous of
>> MessageHandlers to callwhen a web socket message arrives.
>
> I've been working through this in our implementation. (Decoders is a
> different/related/bigger issue.)
>
> More comments inline, but the summary is I think it's best to only allow
> one Text handler and one Binary handler, and throw an
> IllegalStateException at registration time if more than one of each type
> is registered.
>
>>
>> Principles
>>
>> Each web socket message is handled by at most one message handler
>
> Yes.
>
>> Messages that are unhandled result in calls to onError/_at_WebSocketError
>> callbacks, so developers can always know if a message does not get handled
>
> Yes.
>
>> Developer provided decoders are chosen before platform decoders.
>
> Our decoder logic is messed up for bigger reasons, but I want to put
> that discussion off to a different thread.
>
>> If a decoder fails, the error is delivered and no more decoders are
>> attempted.
>
> Ditto. (decoders messed up).
>> MessageHandlers for custom objects (provided a Decoder exists) are
>> chosen over the basic MessageHandlers
>
> Ditto. (decoders messed up).
>>
>> Process
>
> Comment at end.
>>
>> 1. a whole string message arrives
>>
>> a) if there is an MessageHandler.AsyncText handler - call it once with
>> the whole string and stop, otherwise continue...
>> b) if there is an MessageHandler.CharStream handler - call it once
>> using the whole string as the source and stop, otherwise continue...
>> c) if there is a MessageHandler.DecodedObject<T> where T is not
>> String, then try to find a Decoder.Text<T> or a Decoder.TextStream<T>.
>> Look, in order, through developer provided ones (single list, may
>> contain both Text and TextStream types). Then look through platform
>> provided ones. Use the first match to decode it. If the decode
>> completes without error, call the MessageHandler and stop, if not,
>> call the onError/_at_WebSocket method with the decode exception and stop.
>> If there is no suitable Decoder, continue....
>> d) if there is a MessageHandler.Text handler handler, call it, using
>> the first developer provided Decoder.TextStream<String> or
>> Decoder.Text<String>, if any.
>> e) If the message is still unhandled, call back on the
>> onError/_at_WebSocketError method. We may need a new exception type for
>> Unhandledmessages.
>>
>> 2) a whole binary message arrives: use analogous process to 1)
>>
>> 3) the first piece of a chunked string message arrives.
>>
>> a) if there is an MessageHandler.AsyncText handler - call it
>> repeatedly until all the message has arrived and stop, otherwise
>> continue..
>> b) if there is an MessageHandler.CharStream handler - call it with a
>> Reader linked to the incoming parts, and stop, otherwise continue..
>> c) if there are MessageHandler.Text or MessageHandler.DecodedObject
>> handlers, wait for all the string pieces to arrive, building the whole
>> message as you go (subject to the buffer limit defined on the
>> *Container). If the buffer limit is exceeded call the
>> onError/_at_WebSocketError method on the endpoint. Otherwise, using the
>> whole message, jump to the analogous steps for 1c), d) and e) to
>> process the complete message.
>>
>> 4) the first piece of a chunked binary message arrives: use analogous
>> process to 3)
>
> Imagine the replacement specification:
>
> 1) If a text message comes in (chunked or not), the single text
> MessageHandler is used.
>
> 2) If a binary message comes in (chunked or not), the single binary
> MessageHandler is used.
>
> Done.
>
> I don't think there's any practical power lost by this restriction, and
> the limitation is far outweighed by the benefit of a simpler definition.
I must confess that my own implementation work got stuck in the weeds of
working with HTTP upgrade before I got distracted by other work and I
haven't made much progress; certainly not enough to comment on this
based on implementation experience. That said...
My instinct as I read Danny's proposal was that it was looking awfully
complicated and that a cleaner solution would be desirable if such a
thing was possible. Scott's proposal looks like that cleaner solution
and gets my +1 with the caveat that I haven't looked at implementing it.
Mark