James (hi! :)

On Fri, Feb 16, 2018 at 12:55 AM, James Roper <ja...@lightbend.com> wrote:
> The question for me then is whether there is value in introducing an
> additional higher level API (ie, a reactive streams based API) for the
> purposes of integration with other libraries that provide RS support.

I have mixed feeling about this.

I first tried to push the WebSocket APIs to be Flow-based when they
were slated for JDK 9 official inclusion.
As the WebSocket APIs were moved to incubation and are now slated for
JDK 11, it may be worth considering again whether it's the case to
provide a Flow-based APIs.

However, Pavel's point about the limits of the Flow APIs still stand,
so a Flow API may be useful, but less generic.

Another point that makes me feeling uncertain is the good comment by
Konrad Malawski about the design of Akka Streams versus e.g. Spring's
Flowable, where the former does not implement RS or Flow interfaces,
while the latter does.
Now that we have the dichotomy of RS and JDK's Flow, it is easy for
Akka Stream implement methods such as asRSPublisher() and
asFlowPublisher() so that they work in both environments (with - yuck
- multi-release jars).
It would be harder for Spring's Flowable to provide support for both
RS and Flow.

So at the end I would like to see a *separate* Flow API on top of the
current WebSocket API, but who's going to implement it ?
Would be great to standardize a community effort, but even better if
the JDK provided it.

> Introducing another API, regardless of what that API is, obviously has
> drawbacks as it increases the surface area of the API, and thus complexity,
> and also potentially introduces confusion for application developers as they
> now have two different ways of achieving things, and they need to know which
> to use when. So, the value of that API must be high enough to outweigh those
> drawbacks. I strongly believe that a Reactive Streams based API does add
> enough value to do that - and the post that I shared in my previous email
> demonstrates how an ecosystem where reactive streams is embraced can provide
> a lot of value to application developers. So I'm happy to talk more here
> about use cases and code samples etc if you don't agree here.

I personally don't question the value of a RS or Flow API.
It's just a matter of resources - we can ask Oracle to do it, but if
they don't have resources to do it, then the road ahead is
I see better a Flow wrapper of the JDK WebSocket APIs under the
Reactive Extension (https://github.com/Reactive-Extensions) or
Reactive Streams (https://github.com/Reactive-Streams) umbrella.
That would perhaps have less resource issues and still give a unique
library rather than a gazillion similar wrappers.

> For signalling errors upstream, in all the cases that I've worked with,
> we've never found a reason that sending the error downstream, and just
> cancelling upstream, is a problem. At the end of the day, there is only one
> thing that can fail, the TCP connection, and if it fails, both upstream and
> downstream will fail - there is no such thing as a half failure in TCP.

HttpServlet.service() allows to throw exceptions that the Servlet
container must handle by running the error page algorithm, which is
user code.
A Subscriber (provided by a library) encounters an exception while
performing its job.
Since it comes from a library, the library itself does not know how to
handle the error because it does not know in what environment it is
being used.
The common solution I saw in RS libraries for this is to provide
library specific APIs that registers a callback that is invoked in
case of errors.
Another common solution is to have an inverse RS that relays errors in
the opposite direction.
With this library specific APIs, an app running in a Servlet Container
can trigger the error page algorithm depending on the error provided
by the library.
In this way, the error is reported upstream but using an out-of-band
channel specific to each RS library.
And it is *necessary* to notify the error upstream.

Now we can argue forever about whether the mechanism should be part of
the RS APIs or not (e.g. Subscription.cancel(Throwable)), but the
decision has been made and it's not there, and can be done with an
out-of-band, library-specific, callback.
I'm not trying to change the RS APIs - I tried already (hello Viktor
:) and been convinced that the minimalist design has advantages and
that the couple of things that may be lacking can be done anyway with
little effort.

However, the fact that the minimalism of the RS API does not include a
notify-errors-upstream mechanism does not mean that it's not necessary
or not useful.

I'm pretty sure that writing a WebSocket proxy would require such
notify-errors-upstream mechanism, so a generic RS wrapper around the
JDK WebSocket APIs would need to consider that - might be a callback
or a returned Publisher in the opposite direction.
I may be proven wrong - I have not written it myself and for this kind
of things often the details are hidden until a serious implementation
effort is attempted.

Thanks !

Simone Bordet
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz

Reply via email to