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 complicated. 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