hi Pavel,

On Thu, Feb 22, 2018 at 8:43 AM, Pavel Rappo <pavel.ra...@oracle.com> wrote:

> 1. If there is no error reporting, then how would the user know if there's
> something wrong with the data they send? I'm talking about
> incomplete/malformed
> UTF-8, fragments intermixing, sending messages after a Close message has
> been
> sent, etc. How should the user troubleshoot a situation where the
> WebSocket's
> internal Subscriber cancels the subscription unexpectedly? We can't
> perform all
> the checks during a message creation. Some messages could not be checked up
> until they appear in some context. For example, a text fragment is a okay
> per
> se. But if it appears in the midst of a fragmented binary message, it is
> not
> okay. Should the API not allow fragmented (partial) messages then? Or
> should we
> provide error reporting out-of-band in relation to Flow? If we allow only
> whole
> messages, then we are not flexible enough to support streaming. In other
> words
> the case of an arbitrarily large message that does not have to be assembled
> prior to consumption.

Charset encoding issues aside, are these represented with specific
exceptions, and how much can the application do with them? I don't know the
fragments intermixing issue but can the application recover from that? It
is of course more useful for the API to expose error information for each
sent message, but if those are low level errors, treated as terminal, then
only the first one practically matters.

I'm unsure about the exact meaning of fragments​. JSR-356 has partial
messages, which if I recall were explicitly called out in the spec as not
being different from (and not 1-for-1 with) WebSocket fragments. I'll
assume that you mean the same (i.e. the send methods that take an extra
isLast flag). WebSocket is not an application-level protocol and in my
experience, streaming by splitting large content, is a higher level
concern. For example the JavaScript client for STOMP over WebSocket some
time ago started splitting larger STOMP messages along 16K boundaries to
work better with the default buffer sizes of most servers. I'm not saying
such feature shouldn't be present but I don't think it's a must. If
required, one way to represent it is to allow writing with a

> 2. How should the user close their side of the communication? There seems
> to be
> a mismatch in the protocols. WebSocket is bidirectional and relies on Close
> messages. Flow is unidirectional-ish and relies on cancellation through
> onComplete/onError and cancel signals. If the user has no more messages to
> publish, the user may wish to send a Close message with a status code and a
> reason. If instead we rely on onComplete/onError being called then we
> loose the
> ability to provide these extra pieces of information. What should we choose
> here? To not allow a Close message to be sent or to require the user to
> signal
> onComplete() after a Close message has been signalled through onNext().
> Maybe
> there should not be a representation of a Close message at all. Maybe we
> should
> leave it as a protocol low-level detail. But then, how should the API
> deliver
> the received status code and the reason of a Close message it receives?
> Should
> it translate the received Close message to onComplete()/onError()
> depending on
> this message's contents?

I think the API can provide such a close(CloseStatus) method. That would
result in a cancellation of the write Publisher.

> 3. WebSocket protocol mandates a peer should send a Close message as soon
> as
> practical after receiving one. In the current API it is implemented using a
> CompletionStage returned from the WebSocket.Listener.onClose method. How
> should
> we implement this using Flow?

It is hard to discuss on this level of detail without a POC.

I'd assume the API exposes a "read" Publisher<WebSocket>, a way to send
with a "write" Publisher<WebSocket> and some Handler/Listener that returns
Publisher<Void> (or CompletionStage) for when handling is complete. The
"read" Publisher would complete when the server closes. The Publisher<Void>
from the Handler/Listener would complete when all is handled.

> Sure one may recycle buffers transparently. But only if the
> buffer type supports it. io.netty.buffer.PooledByteBufAllocator provides
> instances of io.netty.buffer.ByteBuf. Not java.nio.ByteBuffer. The latter
> one
> does not have any release/free/dispose/etc. methods and semantics.

​If the API exposed some Consumer<ByteBuffer> callback to be applied to
buffers that have been written, then such a pool could also be implemented

> P.S. How may purely RS WebSocket APIs are there? If there are some, we can
> probably
> learn from their experience and make things a bit better. Otherwise I
> don't see
> why we should create one more of them. Would you rather have something
> low-level, you could then implement your high-level API that is most
> relevant to
> your case?

You can see the reactive WebSocket API facade (abstracting different
clients) in the Spring Framework:


Reply via email to