JDBC Next questions regarding j.u.c.Flow integration
douglas.surber at oracle.com
Fri Oct 6 21:34:07 UTC 2017
See inline below.
> On Oct 6, 2017, at 12:40 PM, Rossen Stoyanchev <rstoyanchev at pivotal.io> wrote:
> hi Douglas,
> First of all thank you for engaging with the community.
> > The current version of the API needs back pressure in two places, to limit the rate at which Operations are created/submitted and to limit the rate at which rows are processed.
> What's lacking from the above statement is the application perspective. As a consumer of row data I would expect the ability to apply back pressure against the source and get only as many rows as requested. In a scenario where a web application consumes rows of data with back pressure that propagates all the way to the HTTP connection, if the HTTP connection is too slow, back pressure can be applied against the producer of the data to slow down. This is not an imaginary scenario. You can run such applications today with Reactive Streams as the glue from HTTP servers through to reactive NoSQL data drivers.
I’m sorry I wasn’t clear. The second case, “limiting the rate at which rows are processed” should have been “limiting the rate at which rows are produced”, exactly what you describe.
As to whether monadic programming or reactive streams are a better fit to database access, I think that is very much a case of “it depends”. As I said above we only find two places in the existing API where back pressure is needed. The API has to solve many other problems. Forcing those other concerns into a reactive stream framework is problematic. Our experience suggests that while Operation submission and row production occasionally require back pressure, in a large majority of cases they do not. Forcing all of database access into a reactive stream framework to satisfy a relatively small number of use cases seems like a poor trade off.
That said, use cases where back pressure is needed are valid and should be addressed. And if the rest of the use cases can comfortably be handled in a reactive stream framework then such an API would be a reasonable possibility for async database access. Whether through historical accident or our limitations we were not able to find a unified approach based on reactive streams that met our goals, including integration with Java SE. We believe we have developed an approach based on computational monads that does meet all the goals though it is a bit krufty around the back pressure use cases.
If the community can develop a new API or a modification to the existing API that meets the design goals using reactive streams there is no question that it would be considered. We are not wed to this proposal, but we would like to have a solution for the Java 10 equivalent release.
> > The Java Class Library Team strongly encouraged us to use CompletableFuture. While they did not discourage use of Flow they did not emphasize it. One of the design goals of the API is to integrate well with Java SE and CompletableFuture seemed to do that better than Flow.
> Indeed there is a conundrum here. Reactive Streams provides a crucial mechanism (summarized on Flow.java and also reactive-streams.org <https://urldefense.proofpoint.com/v2/url?u=http-3A__reactive-2Dstreams.org&d=DwMFaQ&c=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY057SbK10&r=ChRVNBZ3Ru5F7CzL9kG_sNBRUO0uuqD6z6ltcMO-LbA&m=qLDED7gsGb7I39BLgrQd1UlnGkU4hIPOASN8dvggWSs&s=bMeMJwLU_-IxRKGV-BATtV2Y2eI1lFyfwHqUghrR9RA&e=>) but as an API it is very low level and ideal for direct use in applications. It would result in the callback hell that your presentation mentions. At the same time CompletableFuture has the nice continuations style API that applications would want to use but does not provide back pressure and it only represents a single result while here we're talking about modelling rows of data.
> Doug Lea summarized the various async API options in Java in the initial Flow announcement :
> CompletableFuture/CompletionStage best supports
> continuation-style programming on futures, and java.util.stream best
> supports (multi-stage, possibly-parallel) "pull" style operations on
> the elements of collections. Until now, one missing category was
> "push" style operations on items as they become available from an
> active source.""
> JDBC fits that last category and here is him again later on defending the decision to include Reactive Streams contracts in the JDK . His argument was that those interfaces are needed in the JDK itself for socket and other I/O APIs that will be designed in the future. I wonder what Doug Lea would advise us here? It would be great for him to weigh in.
> Those of us in the community who have been down this road of designing reactive APIs understand that there is a solution to the conundrum even if it wasn't obvious to us either in the beginning. The preferred approach would be to expose a Reactive Streams API in order to support pub-sub with back pressure. Then layer a declarative API on top of use in applications. It's trivial to to CompletableFuture for something out of the box. Keep in mind also that a Flow-based API would be immediately usable from RxJava, Reactor, and other Reactive Streams libraries. In other words there will be great value for a very large audience and the choice of Flow will not lead to callback hell. The other way around, an API is designed around CompletableFuture, would mean that reactive pressure has to be built on top. The other difference is that CompletableFuture does not allow for deferred initiation of an operation like Reactive Streams does and also the Stream API. So while CompleteableFuture is the best choice for an application-level API based on what's available in the Java class library, it is not the best choice to work with and the JDK does have Flow now to serve as an alternative to be considered at least.
> For an important decision like that, personally I would prefer a more explicit answer from the Java Class Library Team rather than the passive "they did not emphasize Flow so much". What is their take on why Flow was added to the JDK if not for these kinds of pub-sub scenarios with latency such as Async JDBC and the HTTP/2 client?
>  http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013641.html <https://urldefense.proofpoint.com/v2/url?u=http-3A__cs.oswego.edu_pipermail_concurrency-2Dinterest_2015-2DJanuary_013641.html&d=DwMFaQ&c=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY057SbK10&r=ChRVNBZ3Ru5F7CzL9kG_sNBRUO0uuqD6z6ltcMO-LbA&m=qLDED7gsGb7I39BLgrQd1UlnGkU4hIPOASN8dvggWSs&s=iQ91wb2E1zfUK99h9IIzEIw27VXMRjjmEm3hqu8MmEg&e=>
>  http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/013690.html <https://urldefense.proofpoint.com/v2/url?u=http-3A__cs.oswego.edu_pipermail_concurrency-2Dinterest_2015-2DJanuary_013690.html&d=DwMFaQ&c=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY057SbK10&r=ChRVNBZ3Ru5F7CzL9kG_sNBRUO0uuqD6z6ltcMO-LbA&m=qLDED7gsGb7I39BLgrQd1UlnGkU4hIPOASN8dvggWSs&s=6IobfNJERBolKYgz-zIDliUNl1vMn6-AVEE4NCJ-Xy8&e=>
More information about the jdbc-spec-discuss