[concurrency-interest] Upcoming jdk9 j.u.c JEP

Greg Wilkins gregw at webtide.com
Thu Jul 23 18:35:12 EDT 2015


On 24 July 2015 at 00:23, Doug Lea <dl at cs.oswego.edu> wrote:

>
> * Reactive-stream users may be disappointed that we do not include any
> net/IO-based Flow.Publisher/Subscriber classes, considering that
> reactive-streams are mainly motivated by net-based frameworks.  The
> reasons for triaging these out are that (1) IO generally falls outside
> of java.util.concurrent (2) Most net-based frameworks seem to use
> custom data representation etc (e.g., JSON) that are even further out
> of scope.  However class SubmissionPublisher can be used as an adaptor
> to turn just about any kind of source into a Publisher, so provides a
> nearly universal way of constructing a good non-custom Publisher even
> from IO-based sources.  (Also notice that SubmissionPublisher can
> serve as the basis of other actor-like frameworks, including those
> turning off back-pressure by calling
> subscription.request(Long.MAX_VALUE) in onSubscribe).
>
>

Doug et al,

The Jetty project has been experimenting with the reactive streams API:
https://github.com/jetty-project/jetty-reactive albiet not with the JDK-9
version of it, but inspired by the proposed inclusion of it.

We very much like the API and what it can bring to our space.  We don't see
that it needs direct IO support and that it's power is actually bridging
domains with a good asynchronous model that supports flow control.

We've also begun some preliminary discussions about developing RS based
proposal for the Servlet 4.0 specification.    Currently the Servlet API
does well support asynchronous IO and behaviour, but the API is deceptively
difficult to use correctly and gives no support for back pressure.   With
RS's we can envisage solutions that look like:

   - A database provides a RS Producer that provides the large results of a
   query asynchronously from a remote database server
   - Some business logic is encapsulated as a RS Processor subscribed to
   the database producer
   - Some framework provided  Porocessors subscribe to the business logic
   Processor to perform a chain of functions such as serialization, compression
   - A container provided Subscriber terminates the chain and sends the
   resulting byte out over HTTP/HTTP2 or Websocket.   The flow control
   mechanisms of these protocols would be the basis of the RS back pressure.

In such solutions, a full HTTP/2 flow control window would result in back
pressure on the remote database server, allowing threadless waiting without
unlimited queuing of data.

However, we have a significant concern with the API in that we do not like
it's error handling design.  Specifically that it is asymmetric and an
error in the middle of a chain of processors can be propagated downstream
with onError(Throwable) but can only be propagated upstream with cancel().

We believe that cancel without reason is an insufficient semantic to build
a robust ecosystem of RS Processors that can be used to build
applications.   Consider the above example, it would be ideal if the object
serialization was handled by a 3rd party Processor (let's say
JSONEncodingProcessor). If the business logic erroneously sent an
non-jsonable object, or if the JSON converter was incorrectly configured
then the JSONEcondiingProcessor could encounter an error during its
onNext(Object item) handling and it's only permitted handling of that is to
cancel the stream, without explanation.

I have raised this as an issue on the RS github and it the current
recommendation is to log and cancel:
https://github.com/reactive-streams/reactive-streams-jvm/issues/271#issuecomment-121974544
However I believe that log and cancel is a insufficient semantic.   Logging
in assembled applications is often fraught as each component provider will
fight over which logging framework is best.  RS chains may cross
jurisdictional boundaries and logs may not even be readily available.

The solution we see is to replace/augment cancel() with either
cancel(Throwable reason) or an upstream onError(Throwable reason).  I
acknowledge that the passed reason may not always be meaningful to the
upstream processors and publishers, but it is better to ignore a
meaningless reason than to be ignorant of a meaningful one.

When considering this API, we have to look beyond usages that work well and
consider usages that will fail well also!

cheers

-- 
Greg Wilkins <gregw at webtide.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20150724/3a56c27c/attachment-0001.html>


More information about the Concurrency-interest mailing list