ignite-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrey Mashenkov <andrey.mashen...@gmail.com>
Subject Re: [DISCUSSION] IgniteFuture class future in Ignite-3.0.
Date Fri, 02 Apr 2021 09:00:46 GMT
Ivan,
thanks for the link. I think, now I've got what you mean.

I don't think we want to have any framework as a dependency and rely on
their lifecycle, roadmaps goals and
bother about compatibility.
JDK classes are well-known and reactive frameworks usually have converters
to/from CompletableFuture [1] [2].
So, users are free to choose any reactive framework.

I think will need reactive abstractions in near future for Queries API and
maybe Transaction API design.
These projects are good enough where we can get inspiration.

[1]
https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#fromFuture-java.util.concurrent.CompletableFuture-
[2]
https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/rxjava3/internal/jdk8/CompletableFromCompletionStage.java

On Thu, Apr 1, 2021 at 1:29 PM Ivan Pavlukhin <vololo100@gmail.com> wrote:

> Andrey,
>
> > Reactive abstractions look more suitable for Queries rather than
> > cache/table async operations and don't offer the power of chaining like
> > CompletableStage.
>
> Could you please elaborate what capabilities do you mean? AFAIK there
> are quite powerful APIs for singular reactive abstractions as well.
> E.g. [1].
>
> [1]
> https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html
>
> 2021-04-01 12:33 GMT+03:00, Andrey Mashenkov <andrey.mashenkov@gmail.com>:
> > Val,
> > I just complain JDK CompletableFuture itself is not ideal, but already
> > implemented, well-known and tested.
> > It still a good alternative compared to custom future implementation to
> me.
> >
> > Ok, I feel most of us agree with CompletableFuture as a replacement for
> > custom IgniteFuture.
> > Let's try to use it, but keep in mind that we MUST return a defective
> copy
> > (via copy() or minimalStage()) to user to prevent misusage on the user
> > side.
> > It would be nice if we'll follow the same requirement in our internal
> code,
> > e.g. if a component returns a future that further can be used in other
> > components, especially in custom plugins.
> >
> > Ivan, thanks for the example.
> > Reactive abstractions look more suitable for Queries rather than
> > cache/table async operations and don't offer the power of chaining like
> > CompletableStage.
> > AFAIK, guys who involved in SQL engine development based on Calcite
> already
> > use reactive patterns.
> >
> >
> > On Thu, Apr 1, 2021 at 3:15 AM Ivan Pavlukhin <vololo100@gmail.com>
> wrote:
> >
> >> Folks,
> >>
> >> Regarding Reactive abstractions. While it might look too complex for
> >> simple KV cases it can be quite powerful for queries. Also there are
> >> known solutions for cancellation, backpressure and flow control. It
> >> can greatly simplify things for users familiar with Reactive
> >> programming rather than learning Ignite-specific Query/QueryCursor
> >> API.
> >>
> >> Also it looks like there are well-defined semantics [1]. E.g.
> >> cancellation seems to be defined much better than for
> >> CompletableFuture.
> >>
> >> [1]
> >> https://github.com/reactive-streams/reactive-streams-jvm#specification
> >>
> >> 2021-03-31 21:30 GMT+03:00, Valentin Kulichenko <
> >> valentin.kulichenko@gmail.com>:
> >> > Hi Andrey,
> >> >
> >> > Please see below.
> >> >
> >> > -Val
> >> >
> >> > On Wed, Mar 31, 2021 at 7:55 AM Andrey Mashenkov
> >> > <andrey.mashenkov@gmail.com>
> >> > wrote:
> >> >
> >> >> CompletableFuture cancellation will not work as many users expected.
> >> >> Javadoc says:
> >> >> /* Since (unlike {@link FutureTask}) this class has no direct
> >> >> * control over the computation that causes it to be completed,
> >> >> * cancellation is treated as just another form of exceptional
> >> >> * completion.
> >> >> */
> >> >>
> >> >
> >> > Let's not make assumptions about the expectations of the users. That's
> >> > exactly why I initially leaned towards a custom interface as well, but
> >> > that's a mistake.
> >> > Indeed, this contract might look weird to us, because the current
> >> > version
> >> > of Ignite behaves differently. However, there are much more developers
> >> > using CompletableFuture and other standard async frameworks, than
> >> > developers using the async functionality of Ignite. Therefore, our
> >> > intuitions can easily be wrong.
> >> >
> >> >
> >> >> Completion of a child future doesn't trigger the completion of a
> >> >> parent.
> >> >> So, we will need to extend the future anyway.
> >> >>
> >> >
> >> > First of all, as Pavel mentioned, you can attach your own listener
> >> > before
> >> > returning a CompletableFuture to the user. You don't need to extend.
> >> > Second of all, there is still a discussion to be had on whether the
> >> parent
> >> > needs to be completed. I don't actually think it's obvious, and most
> >> likely
> >> > it's case by case. With CompletableFuture you have enough flexibility
> >> > to
> >> > control the behavior.
> >> >
> >> >
> >> >>
> >> >> Also, cancel() method contract differs from IgniteFuture in 2.0,
> >> >> Completable method return true if the future was cancelled,
> >> >> but IgniteFuture return true only if it wasn't cancel prior the call.
> >> >> Thus, if cancel() was called twice we will have different results for
> >> >> CompletableFuture and IgniteFuture,
> >> >> that makes CompletableFuture barely usable for our internal purposes.
> >> >>
> >> >
> >> > It doesn't really matter how IgniteFuture in 2.0 behaves. It was
> >> > created
> >> > long before continuations and other async concepts became mainstream
> >> > (in
> >> > Java world at least).
> >> > Also, we don't have to use it for internal purposes, of course. I'm
> >> > only
> >> > talking about public APIs.
> >> >
> >> >
> >> >>
> >> >> BTW, CompletableFuture.anyOf() still can be used, see
> >> >> CompletionStage.toCompletableFuture() contract.
> >> >>
> >> >
> >> > In my view, this actually kills the idea of a custom future.
> Basically,
> >> > the proposal is to introduce a custom entity to restrict access to
> some
> >> of
> >> > the CompletableFuture methods, but then allow to convert this custom
> >> entity
> >> > to a CompletableFuture that has all the methods. This makes zero sense
> >> > to
> >> > me.
> >> >
> >> >
> >> >>
> >> >> The more I learn about CompletableFuture the stronger my opinion
> about
> >> >> overriding it.
> >> >>
> >> >>
> >> >> On Wed, Mar 31, 2021 at 9:31 AM Denis Garus <garus.d.g@gmail.com>
> >> wrote:
> >> >>
> >> >> > > Stripping them from such functionality, which they are used to,
> is
> >> >> > > most
> >> >> > likely a bad idea.
> >> >> >
> >> >> > Completely agree with this point of view.
> >> >> > Moreover, a user can pass CompletableFuture to another library to
> do
> >> >> > any
> >> >> > manipulations.
> >> >> > So if we want to introduce our class instead of the java class, we
> >> >> > should
> >> >> > have solid arguments;
> >> >> > otherwise, it can be a reason for irritation.
> >> >> >
> >> >> > ср, 31 мар. 2021 г. в 09:06, Pavel Tupitsyn <ptupitsyn@apache.org
> >:
> >> >> >
> >> >> > > Val,
> >> >> > >
> >> >> > > > we can have an IgniteFuture that extends CompletableFuture.
> >> >> > > > This might be useful if want the cancel() operation to cancel
> >> >> > > > the
> >> >> > > > underlying operation
> >> >> > >
> >> >> > > I think we can subscribe to the cancellation of the
> >> CompletableFuture
> >> >> > > and cancel the underlying operation without an extra class,
> >> >> > > something like
> >> >> > >
> >> >> > >         fut.exceptionally(t -> {
> >> >> > >             if (t instanceof CancellationException) {
> >> >> > >                 // Cancel Ignite operation
> >> >> > >             }
> >> >> > >         });
> >> >> > >
> >> >> > > On Wed, Mar 31, 2021 at 7:45 AM Valentin Kulichenko <
> >> >> > > valentin.kulichenko@gmail.com> wrote:
> >> >> > >
> >> >> > > > These are actually some interesting points. As I'm thinking
> more
> >> >> about
> >> >> > > > this, I'm leaning towards changing my opinion and voting for
> the
> >> >> > > > CompletableFuture. Here is my reasoning.
> >> >> > > >
> >> >> > > > First, it's important to keep in mind that CompletableFuture is
> >> not
> >> >> an
> >> >> > > > interface that we will implement, it's an implemented class.
> >> >> Therefore,
> >> >> > > > some of the concerns around complete() and cancel() method are
> >> >> > > > not
> >> >> > really
> >> >> > > > relevant -- it's not up to us how these methods behave, they're
> >> >> already
> >> >> > > > implemented.
> >> >> > > >
> >> >> > > > Second, CompletableFuture does provide some useful
> functionality
> >> >> (anyOf
> >> >> > > is
> >> >> > > > one of the examples). I can even envision users wanting to
> >> complete
> >> >> the
> >> >> > > > future under certain circumstances, e.g. after a timeout, using
> >> >> > > > the completeOnTimeout method. Stripping them from such
> >> >> > > > functionality,
> >> >> > > which
> >> >> > > > they are used to, is most likely a bad idea.
> >> >> > > >
> >> >> > > > And finally, we can have an IgniteFuture that extends
> >> >> > CompletableFuture.
> >> >> > > > This might be useful if want the cancel() operation to cancel
> >> >> > > > the
> >> >> > > > underlying operation. This way we keep all the functionality of
> >> >> > > > CompletableFuture while keeping a certain amount of flexibility
> >> for
> >> >> > > > specific cases.
> >> >> > > >
> >> >> > > > Thoughts?
> >> >> > > >
> >> >> > > > -Val
> >> >> > > >
> >> >> > > >
> >> >> > > > On Tue, Mar 30, 2021 at 5:36 AM Denis Garus
> >> >> > > > <garus.d.g@gmail.com>
> >> >> > wrote:
> >> >> > > >
> >> >> > > > > > Completing future from outside will never respect other
> >> >> subscribers
> >> >> > > > that
> >> >> > > > > > may expect other guatantees.
> >> >> > > > >
> >> >> > > > > For example, if we talk about public API like IgniteCache,
> >> >> > > > > what
> >> >> > > > subscribers
> >> >> > > > > may expect other guatantees?
> >> >> > > > > IMHO, the best solution is to get the well-known standard
> >> >> > > > > interface
> >> >> > to
> >> >> > > a
> >> >> > > > > user, and he will be happy.
> >> >> > > > >
> >> >> > > > > But when we talk about internal classes like "exchange
> future"
> >> >> > > > > they
> >> >> > > could
> >> >> > > > > be custom futures if convenient.
> >> >> > > > >
> >> >> > > > > вт, 30 мар. 2021 г. в 15:25, Atri Sharma <atri@apache.org>:
> >> >> > > > >
> >> >> > > > > > IMO the only way Ignite should cancel computations is iff
> >> >> > > > > > cancel
> >> >> > > method
> >> >> > > > > is
> >> >> > > > > > invoked, not implicitly if complete is invoked.
> >> >> > > > > >
> >> >> > > > > > On Tue, 30 Mar 2021 at 4:58 PM, Denis Garus
> >> >> > > > > > <garus.d.g@gmail.com
> >> >> >
> >> >> > > > wrote:
> >> >> > > > > >
> >> >> > > > > > > Hello!
> >> >> > > > > > >
> >> >> > > > > > > > Let's say a user started a compute with fut =
> >> >> > > > compute.runAsync(task);
> >> >> > > > > > > > and now calls fut.complete(someVal); Does this mean
> that
> >> >> Ignite
> >> >> > > no
> >> >> > > > > > longer
> >> >> > > > > > > needs to execute the task?
> >> >> > > > > > > > If the task is currently running, does it need to be
> >> >> canceled?
> >> >> > > > > > >
> >> >> > > > > > > Yes, this case looks like Ignite should cancel
> >> >> > > > > > > computations
> >> >> > > because a
> >> >> > > > > > user
> >> >> > > > > > > wants to complete the future. Why not?
> >> >> > > > > > > If there will be an opportunity to cancel a future, why
> is
> >> it
> >> >> > > > > > > a
> >> >> > bad
> >> >> > > > > > option
> >> >> > > > > > > to finish a future through a complete() method?
> >> >> > > > > > >
> >> >> > > > > > > > If you look at Ignite-2 code, you may found a number of
> >> >> places
> >> >> > > > where
> >> >> > > > > we
> >> >> > > > > > > return e.g. exchange futures or partition release
> futures.
> >> >> > > > > > > > Assume the impact if we will return CompletableFuture
> >> >> instead,
> >> >> > > > which
> >> >> > > > > > can
> >> >> > > > > > > be completed in 3-rd party plugin by mistake?
> >> >> > > > > > >
> >> >> > > > > > > If exchange futures or partition release futures can be
> >> >> returned
> >> >> > to
> >> >> > > > > 3-rd
> >> >> > > > > > > party plugin by mistake, it is poor encapsulation.
> >> >> > > > > > > And if it will be IgniteFuter rather than
> CompletedFuture,
> >> >> > anyway,
> >> >> > > > this
> >> >> > > > > > can
> >> >> > > > > > > harm.
> >> >> > > > > > >
> >> >> > > > > > > вт, 30 мар. 2021 г. в 13:14, Andrey Mashenkov <
> >> >> > > > > > andrey.mashenkov@gmail.com
> >> >> > > > > > > >:
> >> >> > > > > > >
> >> >> > > > > > > > Guys,
> >> >> > > > > > > >
> >> >> > > > > > > > I want to remember there is one more point to pay
> >> attention
> >> >> to.
> >> >> > > > > > > > Extending Future and CompletableStage is more than just
> >> >> > prevents
> >> >> > > > > > > unexpected
> >> >> > > > > > > > behavior if a user completed the future.
> >> >> > > > > > > >
> >> >> > > > > > > > First of all, it helps us to write safer code as we
> >> >> > > > > > > > won't
> >> a
> >> >> > > method
> >> >> > > > > > > contract
> >> >> > > > > > > > exposed such methods as to a user as to a developer.
> >> >> > > > > > > > If you look at Ignite-2 code, you may found a number of
> >> >> places
> >> >> > > > where
> >> >> > > > > we
> >> >> > > > > > > > return e.g. exchange futures or partition release
> >> >> > > > > > > > futures.
> >> >> > > > > > > > Assume the impact if we will return CompletableFuture
> >> >> instead,
> >> >> > > > which
> >> >> > > > > > can
> >> >> > > > > > > be
> >> >> > > > > > > > completed in 3-rd party plugin by mistake?
> >> >> > > > > > > >
> >> >> > > > > > > > The suggested approach allows us to don't bother if a
> >> >> > > > > CompletableFuture
> >> >> > > > > > > has
> >> >> > > > > > > > to be wrapped or not.
> >> >> > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > > > On Tue, Mar 30, 2021 at 12:22 PM Alexey Goncharuk <
> >> >> > > > > > > > alexey.goncharuk@gmail.com> wrote:
> >> >> > > > > > > >
> >> >> > > > > > > > > Ivan,
> >> >> > > > > > > > >
> >> >> > > > > > > > > My concern with the concept of a user completing the
> >> >> > > > > > > > > future
> >> >> > > > > returned
> >> >> > > > > > > from
> >> >> > > > > > > > > Ignite public API is that it is unclear how to
> >> >> > > > > > > > > interpret
> >> >> this
> >> >> > > > > action
> >> >> > > > > > > > (this
> >> >> > > > > > > > > backs Val's message).
> >> >> > > > > > > > > Let's say a user started a compute with fut =
> >> >> > > > > compute.runAsync(task);
> >> >> > > > > > > and
> >> >> > > > > > > > > now calls fut.complete(someVal); Does this mean that
> >> >> > > > > > > > > Ignite
> >> >> > no
> >> >> > > > > longer
> >> >> > > > > > > > needs
> >> >> > > > > > > > > to execute the task? If the task is currently
> running,
> >> >> > > > > > > > > does
> >> >> > it
> >> >> > > > need
> >> >> > > > > > to
> >> >> > > > > > > be
> >> >> > > > > > > > > canceled?
> >> >> > > > > > > > >
> >> >> > > > > > > > > Using CompletableFuture.anyOf() is a good instrument
> >> >> > > > > > > > > in
> >> >> this
> >> >> > > case
> >> >> > > > > > > because
> >> >> > > > > > > > > it makes the 'first future wins' contract explicit in
> >> the
> >> >> > code.
> >> >> > > > > > Besides
> >> >> > > > > > > > > that, the point regarding the cancel() method is
> >> >> > > > > > > > > valid,
> >> >> > > > > > > > > and
> >> >> > we
> >> >> > > > will
> >> >> > > > > > > need
> >> >> > > > > > > > > some custom mechanics to cancel a computation, so a
> >> >> > > > > > > > > custom
> >> >> > > > > interface
> >> >> > > > > > > that
> >> >> > > > > > > > > simply extends both Future and CompletableStage seems
> >> >> > > reasonable
> >> >> > > > to
> >> >> > > > > > me.
> >> >> > > > > > > > >
> >> >> > > > > > > > > --AG
> >> >> > > > > > > > >
> >> >> > > > > > > > > пн, 29 мар. 2021 г. в 09:12, Ivan Pavlukhin <
> >> >> > > vololo100@gmail.com
> >> >> > > > >:
> >> >> > > > > > > > >
> >> >> > > > > > > > > > Val,
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > There were enough hype around Reactive programming
> >> past
> >> >> > > years.
> >> >> > > > I
> >> >> > > > > > > > > > remind a lot of talks about RxJava. And I suppose
> it
> >> >> worth
> >> >> > to
> >> >> > > > > > > consider
> >> >> > > > > > > > > > it. But it requires some time to study modern
> trends
> >> to
> >> >> > make
> >> >> > > a
> >> >> > > > > > > choice.
> >> >> > > > > > > > > > So far I am not ready to facilitate Reactive API
> for
> >> >> Ignite
> >> >> > > 3.
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > Regarding CompletableFuture.
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > > The point is that currently a future returned
> from
> >> >> > > > > > > > > > > any
> >> >> of
> >> >> > > > > > Ignite's
> >> >> > > > > > > > > async
> >> >> > > > > > > > > > > operations is supposed to be completed with a
> >> >> > > > > > > > > > > value
> >> >> only
> >> >> > by
> >> >> > > > > > Ignite
> >> >> > > > > > > > > > itself,
> >> >> > > > > > > > > > > not by the user. If we follow the same approach
> in
> >> >> Ignite
> >> >> > > 3,
> >> >> > > > > > > > returning
> >> >> > > > > > > > > > > CompletableFuture is surely wrong in my view.
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > My first thoughts was similar. But later I thought
> >> what
> >> >> > > > > > > > > > a
> >> >> > > user
> >> >> > > > > > would
> >> >> > > > > > > > > > like do with returned future. And one of cases I
> >> >> > > > > > > > > > imagined
> >> >> > > was a
> >> >> > > > > > case
> >> >> > > > > > > > > > of alternative result. E.g. a user uses Ignite and
> >> >> another
> >> >> > > data
> >> >> > > > > > > source
> >> >> > > > > > > > > > in his application. He wants to use a value arrived
> >> >> faster.
> >> >> > > He
> >> >> > > > > > > > > > combines 2 futures like
> >> >> > > > > > > > > > CompletableFuture.anyOf(...).
> >> >> > > > > Consequently
> >> >> > > > > > > > > > even if we prohibit CompletableFuture.complete(...)
> >> >> > > explicitly
> >> >> > > > > then
> >> >> > > > > > > it
> >> >> > > > > > > > > > will be possible to create a combination that will
> >> >> > > > > > > > > > allow
> >> >> > > > > premature
> >> >> > > > > > > > > > future completion. After all generally
> >> >> > > > > > > > > > CompletableFuture
> >> >> > is a
> >> >> > > > > > > > > > placeholder for async computaion result and if a
> >> >> > > > > > > > > > user
> >> >> wants
> >> >> > > to
> >> >> > > > > > > > > > substitute result returned from Ignite why should
> we
> >> >> > disallow
> >> >> > > > him
> >> >> > > > > > to
> >> >> > > > > > > > > > do it?
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > Also I found one more suspicious thing with
> >> >> > > CompletableFuture.
> >> >> > > > As
> >> >> > > > > > it
> >> >> > > > > > > > > > is a concrete class it implements a cancel()
> method.
> >> >> > > > > > > > > > And
> >> >> > as I
> >> >> > > > see
> >> >> > > > > > the
> >> >> > > > > > > > > > implementation does not try to cancel underlying
> >> >> > > computations.
> >> >> > > > Is
> >> >> > > > > > not
> >> >> > > > > > > > > > it a problem?
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > 2021-03-29 7:30 GMT+03:00, Valentin Kulichenko <
> >> >> > > > > > > > > > valentin.kulichenko@gmail.com>:
> >> >> > > > > > > > > > > Ivan,
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > It's not really about the "harm", but more about
> >> >> > > > > > > > > > > "what
> >> >> > > should
> >> >> > > > > we
> >> >> > > > > > do
> >> >> > > > > > > > if
> >> >> > > > > > > > > > this
> >> >> > > > > > > > > > > method is called?". Imagine the following code:
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > CompletableFuture<String> fut =
> >> >> > > > > > > > > > > cache.getAsync(key);
> >> >> > > > > > > > > > > fut.complete("something");
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > What should happen in this case?
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > The point is that currently a future returned
> from
> >> >> > > > > > > > > > > any
> >> >> of
> >> >> > > > > > Ignite's
> >> >> > > > > > > > > async
> >> >> > > > > > > > > > > operations is supposed to be completed with a
> >> >> > > > > > > > > > > value
> >> >> only
> >> >> > by
> >> >> > > > > > Ignite
> >> >> > > > > > > > > > itself,
> >> >> > > > > > > > > > > not by the user. If we follow the same approach
> in
> >> >> Ignite
> >> >> > > 3,
> >> >> > > > > > > > returning
> >> >> > > > > > > > > > > CompletableFuture is surely wrong in my view.
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > At the same time, if we take a fundamentally
> >> >> > > > > > > > > > > different
> >> >> > > route
> >> >> > > > > with
> >> >> > > > > > > the
> >> >> > > > > > > > > > async
> >> >> > > > > > > > > > > APIs, this whole discussion might become
> >> >> > > > > > > > > > > irrelevant.
> >> >> For
> >> >> > > > > example,
> >> >> > > > > > > can
> >> >> > > > > > > > > you
> >> >> > > > > > > > > > > elaborate on your thinking around the reactive
> >> >> > > > > > > > > > > API?
> >> >> > > > > > > > > > > Do
> >> >> > you
> >> >> > > > have
> >> >> > > > > > any
> >> >> > > > > > > > > > > specifics in mind?
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > -Val
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > > On Sat, Mar 27, 2021 at 9:18 PM Ivan Pavlukhin <
> >> >> > > > > > > vololo100@gmail.com>
> >> >> > > > > > > > > > wrote:
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > > >> > The methods below shouldn't be accessible for
> >> >> > > > > > > > > > >> > user:
> >> >> > > > > > > > > > >> > complete()
> >> >> > > > > > > > > > >> > completeExceptionaly()
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >> Folks, in case of user-facing API, do you think
> >> >> > > > > > > > > > >> there
> >> >> > is a
> >> >> > > > > real
> >> >> > > > > > > harm
> >> >> > > > > > > > > > >> in allowing a user to manually "complete" a
> >> >> > > > > > > > > > >> future?
> >> >> > > > > > > > > > >> I
> >> >> > > > suppose
> >> >> > > > > a
> >> >> > > > > > > user
> >> >> > > > > > > > > > >> employs some post-processing for future results
> >> >> > > > > > > > > > >> and
> >> >> > > > > potentially
> >> >> > > > > > > > wants
> >> >> > > > > > > > > > >> to have control of these results as well. E.g.
> >> >> premature
> >> >> > > > > > > completion
> >> >> > > > > > > > in
> >> >> > > > > > > > > > >> case when a result is no longer needed is
> >> >> > > > > > > > > > >> possible
> >> >> > usage.
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >> Also I thinkg it might be a good time to ponder
> >> >> > > > > > > > > > >> about
> >> >> > > > > > > Future/Promise
> >> >> > > > > > > > > > >> APIs in general. Why such API is our choice? Can
> >> >> > > > > > > > > > >> we
> >> >> > choose
> >> >> > > > > e.g.
> >> >> > > > > > > > > > >> Reactive API style instead?
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >> 2021-03-27 0:33 GMT+03:00, Valentin Kulichenko <
> >> >> > > > > > > > > > >> valentin.kulichenko@gmail.com>:
> >> >> > > > > > > > > > >> > Andrey,
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >> > I see. So in a nutshell, you're saying that we
> >> >> > > > > > > > > > >> > want
> >> >> to
> >> >> > > > > return
> >> >> > > > > > a
> >> >> > > > > > > > > future
> >> >> > > > > > > > > > >> that
> >> >> > > > > > > > > > >> > the user's code is not allowed to complete. In
> >> >> > > > > > > > > > >> > this
> >> >> > > case,
> >> >> > > > I
> >> >> > > > > > > think
> >> >> > > > > > > > > it's
> >> >> > > > > > > > > > >> > clear that CompletableFuture is not what we
> >> >> > > > > > > > > > >> > need.
> >> >> > > > > > > > > > >> > We
> >> >> > > > > actually
> >> >> > > > > > > > need a
> >> >> > > > > > > > > > >> > NonCompletableFuture :)
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >> > My vote is for the custom interface.
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >> > -Val
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >> > On Fri, Mar 26, 2021 at 2:25 AM Andrey
> >> >> > > > > > > > > > >> > Mashenkov
> >> >> > > > > > > > > > >> > <andrey.mashenkov@gmail.com>
> >> >> > > > > > > > > > >> > wrote:
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >> >> Val,
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> The methods below shouldn't be accessible for
> >> >> > > > > > > > > > >> >> user:
> >> >> > > > > > > > > > >> >> complete()
> >> >> > > > > > > > > > >> >> completeExceptionaly()
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> Returning CompletableFuture we must always
> >> >> > > > > > > > > > >> >> make
> >> a
> >> >> > copy
> >> >> > > to
> >> >> > > > > > > prevent
> >> >> > > > > > > > > the
> >> >> > > > > > > > > > >> >> original future from being completed by
> >> >> > > > > > > > > > >> >> mistake.
> >> >> > > > > > > > > > >> >> I think it will NOT be enough to do that
> >> returing
> >> >> the
> >> >> > > > > future
> >> >> > > > > > to
> >> >> > > > > > > > the
> >> >> > > > > > > > > > >> >> end-user, but from every critical module to
> >> >> > > > > > > > > > >> >> the
> >> >> > outside
> >> >> > > > of
> >> >> > > > > > the
> >> >> > > > > > > > > > module,
> >> >> > > > > > > > > > >> >> e.g. to plugins. The impact of disclosing
> >> >> > > ExchangeFuture,
> >> >> > > > > > > > > > >> >> PartitionReleaseFuture to plugins may be
> >> serious.
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> IgniteFuture<T> extends Future<T>,
> >> >> CompletionStage<T>
> >> >> > > > which
> >> >> > > > > > > > > > >> >> implementation
> >> >> > > > > > > > > > >> >> will just wrap CompletableFuture these issues
> >> >> > > > > > > > > > >> >> will
> >> >> be
> >> >> > > > > > resolved
> >> >> > > > > > > in
> >> >> > > > > > > > > > >> natural
> >> >> > > > > > > > > > >> >> way.
> >> >> > > > > > > > > > >> >> In addition we can force
> toCompletableFuture()
> >> >> method
> >> >> > > to
> >> >> > > > > > > return a
> >> >> > > > > > > > > > >> >> defensive
> >> >> > > > > > > > > > >> >> copy(), that resolves the last concern.
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> On Fri, Mar 26, 2021 at 11:38 AM Konstantin
> >> Orlov
> >> >> > > > > > > > > > >> >> <korlov@gridgain.com>
> >> >> > > > > > > > > > >> >> wrote:
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> > CompletableFuture seems a better option to
> >> >> > > > > > > > > > >> >> > me.
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> > --
> >> >> > > > > > > > > > >> >> > Regards,
> >> >> > > > > > > > > > >> >> > Konstantin Orlov
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> > > On 26 Mar 2021, at 11:07, Pavel Tupitsyn
> <
> >> >> > > > > > > > ptupitsyn@apache.org
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > >> >> > > wrote:
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > > On the one hand, I agree with Alexey.
> >> >> > > > > > > > > > >> >> > > CompletableFuture has complete* methods
> >> which
> >> >> > > should
> >> >> > > > > not
> >> >> > > > > > be
> >> >> > > > > > > > > > >> available
> >> >> > > > > > > > > > >> >> to
> >> >> > > > > > > > > > >> >> > > the user code.
> >> >> > > > > > > > > > >> >> > > This can be solved with a simple
> interface
> >> >> > > > > > > > > > >> >> > > like
> >> >> > we
> >> >> > > do
> >> >> > > > > in
> >> >> > > > > > > Thin
> >> >> > > > > > > > > > >> Client:
> >> >> > > > > > > > > > >> >> > > IgniteClientFuture<T> extends Future<T>,
> >> >> > > > > > CompletionStage<T>
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > > On the other hand:
> >> >> > > > > > > > > > >> >> > > - CompletionStage has toCompletableFuture
> >> >> anyway
> >> >> > > > > (rather
> >> >> > > > > > > > weird)
> >> >> > > > > > > > > > >> >> > > - Other libraries use CompletableFuture
> >> >> > > > > > > > > > >> >> > > and
> >> >> > > > > > > > > > >> >> > > it
> >> >> > > seems
> >> >> > > > to
> >> >> > > > > > be
> >> >> > > > > > > > fine
> >> >> > > > > > > > > > >> >> > > - Using CompletableFuture is the simplest
> >> >> > approach
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > > So I lean towards CompletableFuture too.
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > > On Fri, Mar 26, 2021 at 10:46 AM Alexey
> >> >> > Kukushkin <
> >> >> > > > > > > > > > >> >> > kukushkinalexey@gmail.com>
> >> >> > > > > > > > > > >> >> > > wrote:
> >> >> > > > > > > > > > >> >> > >
> >> >> > > > > > > > > > >> >> > >> I do not like Java's CompletableFuture
> >> >> > > > > > > > > > >> >> > >> and
> >> >> > prefer
> >> >> > > > our
> >> >> > > > > > own
> >> >> > > > > > > > > Future
> >> >> > > > > > > > > > >> >> > (revised
> >> >> > > > > > > > > > >> >> > >> IgniteFuture).
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >> My understanding of the Future (or
> >> >> > > > > > > > > > >> >> > >> Promise)
> >> >> > > pattern
> >> >> > > > in
> >> >> > > > > > > > general
> >> >> > > > > > > > > > is
> >> >> > > > > > > > > > >> >> having
> >> >> > > > > > > > > > >> >> > >> two separate APIs:
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >>   1. Server-side: create, set result,
> >> >> > > > > > > > > > >> >> > >> raise
> >> >> > error,
> >> >> > > > > > cancel
> >> >> > > > > > > > from
> >> >> > > > > > > > > > >> >> > >> server.
> >> >> > > > > > > > > > >> >> > >>   2. Client-side: get result, handle
> >> >> > > > > > > > > > >> >> > >> error,
> >> >> > cancel
> >> >> > > > > from
> >> >> > > > > > > > client
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >> Java's CompletableFuture looks like both
> >> the
> >> >> > > > > client-side
> >> >> > > > > > > and
> >> >> > > > > > > > > > >> >> > >> server-side API. The "Completeable"
> >> >> > > > > > > > > > >> >> > >> prefix
> >> >> > > > > > > > > > >> >> > >> in
> >> >> > the
> >> >> > > > name
> >> >> > > > > > is
> >> >> > > > > > > > > > already
> >> >> > > > > > > > > > >> >> > confusing
> >> >> > > > > > > > > > >> >> > >> for a client since it cannot "complete"
> >> >> > > > > > > > > > >> >> > >> an
> >> >> > > > operation,
> >> >> > > > > > > only a
> >> >> > > > > > > > > > >> >> > >> server
> >> >> > > > > > > > > > >> >> can.
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >> I would create our own IgniteFuture
> >> >> > > > > > > > > > >> >> > >> adding
> >> >> > > > client-side
> >> >> > > > > > > > > > >> functionality
> >> >> > > > > > > > > > >> >> we
> >> >> > > > > > > > > > >> >> > >> currently miss (like client-side
> >> >> cancellation).
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >> пт, 26 мар. 2021 г. в 01:08, Valentin
> >> >> > Kulichenko <
> >> >> > > > > > > > > > >> >> > >> valentin.kulichenko@gmail.com>:
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >>> Andrey,
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>> Can you compile a full list of these
> >> >> > > > > > > > > > >> >> > >>> risky
> >> >> > > methods,
> >> >> > > > > and
> >> >> > > > > > > > > > >> >> > >>> elaborate
> >> >> > > > > > > > > > >> >> > >>> on
> >> >> > > > > > > > > > >> >> > what
> >> >> > > > > > > > > > >> >> > >>> the risks are?
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>> Generally, CompletableFuture is a much
> >> >> > > > > > > > > > >> >> > >>> better
> >> >> > > > option,
> >> >> > > > > > > > because
> >> >> > > > > > > > > > >> >> > >>> it's
> >> >> > > > > > > > > > >> >> > >>> standard. But we need to make sure it
> >> >> actually
> >> >> > > fits
> >> >> > > > > our
> >> >> > > > > > > > needs
> >> >> > > > > > > > > > >> >> > >>> and
> >> >> > > > > > > > > > >> >> > doesn't
> >> >> > > > > > > > > > >> >> > >>> do more harm than good.
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>> -Val
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>> On Thu, Mar 25, 2021 at 12:23 PM Alexei
> >> >> > > Scherbakov
> >> >> > > > <
> >> >> > > > > > > > > > >> >> > >>> alexey.scherbakoff@gmail.com> wrote:
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>>> I think both options are fine, but
> >> >> personally
> >> >> > > lean
> >> >> > > > > > > toward
> >> >> > > > > > > > > > >> >> > >>>> CompletableFuture.
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>> чт, 25 мар. 2021 г. в 17:56, Atri
> >> >> > > > > > > > > > >> >> > >>>> Sharma
> >> <
> >> >> > > > > > > atri@apache.org
> >> >> > > > > > > > >:
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>>> I would suggest using
> >> >> > > > > > > > > > >> >> > >>>>> CompletableFuture
> >> >> > > > > > > > > > >> >> > >>>>> --
> >> >> I
> >> >> > > > don't
> >> >> > > > > > see
> >> >> > > > > > > a
> >> >> > > > > > > > > need
> >> >> > > > > > > > > > >> for
> >> >> > > > > > > > > > >> >> > >>>>> a
> >> >> > > > > > > > > > >> >> > >>>> custom
> >> >> > > > > > > > > > >> >> > >>>>> interface that is unique to us.
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>> It also allows a lower barrier for
> new
> >> >> > > > contributors
> >> >> > > > > > for
> >> >> > > > > > > > > > >> >> understanding
> >> >> > > > > > > > > > >> >> > >>>>> existing code
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>> On Thu, 25 Mar 2021, 20:18 Andrey
> >> >> Mashenkov,
> >> >> > <
> >> >> > > > > > > > > > >> >> > >>> andrey.mashenkov@gmail.com
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>> wrote:
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> Hi Igniters,
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> I'd like to start a discussion about
> >> >> > replacing
> >> >> > > > our
> >> >> > > > > > > > custom
> >> >> > > > > > > > > > >> >> > >>> IgniteFuture
> >> >> > > > > > > > > > >> >> > >>>>>> class with CompletableFuture -
> >> >> > > > > > > > > > >> >> > >>>>>> existed
> >> >> > > > > > > > > > >> >> > >>>>>> JDK
> >> >> > > class
> >> >> > > > > > > > > > >> >> > >>>>>> or rework it's implementation (like
> >> some
> >> >> > other
> >> >> > > > > > > products
> >> >> > > > > > > > > > done)
> >> >> > > > > > > > > > >> to
> >> >> > > > > > > > > > >> >> > >>>>>> a
> >> >> > > > > > > > > > >> >> > >>>>>> composition of CompletionStage and
> >> >> > > > > > > > > > >> >> > >>>>>> Future
> >> >> > > > > > interfaces.
> >> >> > > > > > > > > > >> >> > >>>>>> or maybe other option if you have
> any
> >> >> ideas.
> >> >> > > Do
> >> >> > > > > you?
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> 1. The first approach pros and cons
> >> >> > > > > > > > > > >> >> > >>>>>> are
> >> >> > > > > > > > > > >> >> > >>>>>> + Well-known JDK class
> >> >> > > > > > > > > > >> >> > >>>>>> + Already implemented
> >> >> > > > > > > > > > >> >> > >>>>>> - It is a class, not an interface.
> >> >> > > > > > > > > > >> >> > >>>>>> - Expose some potentially harmful
> >> >> > > > > > > > > > >> >> > >>>>>> methods
> >> >> > like
> >> >> > > > > > > > > "complete()".
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> On the other side, it has copy()
> >> >> > > > > > > > > > >> >> > >>>>>> method
> >> >> > > > > > > > > > >> >> > >>>>>> to
> >> >> > > > create
> >> >> > > > > > > > > defensive
> >> >> > > > > > > > > > >> copy
> >> >> > > > > > > > > > >> >> > >> and
> >> >> > > > > > > > > > >> >> > >>>>>> minimalCompletionStage() to restrict
> >> >> harmful
> >> >> > > > > method
> >> >> > > > > > > > usage.
> >> >> > > > > > > > > > >> >> > >>>>>> Thus, this look like an applicable
> >> >> solution,
> >> >> > > but
> >> >> > > > > we
> >> >> > > > > > > > should
> >> >> > > > > > > > > > be
> >> >> > > > > > > > > > >> >> > >> careful
> >> >> > > > > > > > > > >> >> > >>>>>> exposing internal future to the
> >> outside.
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> 2. The second approach is to
> >> >> > > > > > > > > > >> >> > >>>>>> implement
> >> >> > > > > > > > > > >> >> > >>>>>> our
> >> >> > own
> >> >> > > > > > > interface
> >> >> > > > > > > > > > like
> >> >> > > > > > > > > > >> >> > >>>>>> the
> >> >> > > > > > > > > > >> >> > >>> next
> >> >> > > > > > > > > > >> >> > >>>>> one:
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> interface IgniteFuture<T> extends
> >> >> > > > > > CompletableStage<T>,
> >> >> > > > > > > > > > >> Future<T>
> >> >> > > > > > > > > > >> >> > >>>>>> {
> >> >> > > > > > > > > > >> >> > >>>>>> }
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> Pros and cons are
> >> >> > > > > > > > > > >> >> > >>>>>> + Our interfaces/classes contracts
> >> >> > > > > > > > > > >> >> > >>>>>> will
> >> >> > expose
> >> >> > > > an
> >> >> > > > > > > > > interface
> >> >> > > > > > > > > > >> >> > >>>>>> rather
> >> >> > > > > > > > > > >> >> > >>> than
> >> >> > > > > > > > > > >> >> > >>>>>> concrete implementation.
> >> >> > > > > > > > > > >> >> > >>>>>> + All methods are safe.
> >> >> > > > > > > > > > >> >> > >>>>>> - Some implementation is required.
> >> >> > > > > > > > > > >> >> > >>>>>> - CompletableStage has a method
> >> >> > > > > > toCompletableFuture()
> >> >> > > > > > > > and
> >> >> > > > > > > > > > can
> >> >> > > > > > > > > > >> be
> >> >> > > > > > > > > > >> >> > >>>>> converted
> >> >> > > > > > > > > > >> >> > >>>>>> to CompletableFuture. This should be
> >> >> > > supported.
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> However, we still could wrap
> >> >> > CompletableFuture
> >> >> > > > and
> >> >> > > > > > > don't
> >> >> > > > > > > > > > >> >> > >>>>>> bother
> >> >> > > > > > > > > > >> >> > >> about
> >> >> > > > > > > > > > >> >> > >>>>>> creating a defensive copy.
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> Other project experience:
> >> >> > > > > > > > > > >> >> > >>>>>> * Spotify uses CompletableFuture
> >> >> > > > > > > > > > >> >> > >>>>>> directly
> >> >> > [1].
> >> >> > > > > > > > > > >> >> > >>>>>> * Redis goes the second approach [2]
> >> >> > > > > > > > > > >> >> > >>>>>> * Vertx explicitly extends
> >> >> CompletableFuture
> >> >> > > > [3].
> >> >> > > > > > > > However,
> >> >> > > > > > > > > > >> >> > >>>>>> they
> >> >> > > > > > > > > > >> >> > >> have
> >> >> > > > > > > > > > >> >> > >>>>> custom
> >> >> > > > > > > > > > >> >> > >>>>>> future classes and a number of
> >> >> > > > > > > > > > >> >> > >>>>>> helpers
> >> >> that
> >> >> > > > could
> >> >> > > > > be
> >> >> > > > > > > > > > replaced
> >> >> > > > > > > > > > >> >> > >>>>>> with
> >> >> > > > > > > > > > >> >> > >>>>>> CompletableStage. Maybe it is just a
> >> >> > legacy.'
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> Any thoughts?
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>> [1]
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > >
> >> >> > > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > >
> >> >> > > > > >
> >> >> > > > >
> >> >> > > >
> >> >> > >
> >> >> >
> >> >>
> >>
> https://spotify.github.io/completable-futures/apidocs/com/spotify/futures/ConcurrencyReducer.html
> >> >> > > > > > > > > > >> >> > >>>>>> [2]
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > >
> >> >> > > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > >
> >> >> > > > > >
> >> >> > > > >
> >> >> > > >
> >> >> > >
> >> >> >
> >> >>
> >>
> https://lettuce.io/lettuce-4/release/api/com/lambdaworks/redis/RedisFuture.html
> >> >> > > > > > > > > > >> >> > >>>>>> [3]
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > >
> >> >> > > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > >
> >> >> > > > > >
> >> >> > > > >
> >> >> > > >
> >> >> > >
> >> >> >
> >> >>
> >>
> https://javadoc.io/static/org.jspare.vertx/vertx-jspare/1.1.0-M03/org/jspare/vertx/concurrent/VertxCompletableFuture.html
> >> >> > > > > > > > > > >> >> > >>>>>> --
> >> >> > > > > > > > > > >> >> > >>>>>> Best regards,
> >> >> > > > > > > > > > >> >> > >>>>>> Andrey V. Mashenkov
> >> >> > > > > > > > > > >> >> > >>>>>>
> >> >> > > > > > > > > > >> >> > >>>>>
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>> --
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>> Best regards,
> >> >> > > > > > > > > > >> >> > >>>> Alexei Scherbakov
> >> >> > > > > > > > > > >> >> > >>>>
> >> >> > > > > > > > > > >> >> > >>>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> > >> --
> >> >> > > > > > > > > > >> >> > >> Best regards,
> >> >> > > > > > > > > > >> >> > >> Alexey
> >> >> > > > > > > > > > >> >> > >>
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >> >
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >> --
> >> >> > > > > > > > > > >> >> Best regards,
> >> >> > > > > > > > > > >> >> Andrey V. Mashenkov
> >> >> > > > > > > > > > >> >>
> >> >> > > > > > > > > > >> >
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >> --
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >> Best regards,
> >> >> > > > > > > > > > >> Ivan Pavlukhin
> >> >> > > > > > > > > > >>
> >> >> > > > > > > > > > >
> >> >> > > > > > > > > >
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > --
> >> >> > > > > > > > > >
> >> >> > > > > > > > > > Best regards,
> >> >> > > > > > > > > > Ivan Pavlukhin
> >> >> > > > > > > > > >
> >> >> > > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > > >
> >> >> > > > > > > > --
> >> >> > > > > > > > Best regards,
> >> >> > > > > > > > Andrey V. Mashenkov
> >> >> > > > > > > >
> >> >> > > > > > >
> >> >> > > > > > --
> >> >> > > > > > Regards,
> >> >> > > > > >
> >> >> > > > > > Atri
> >> >> > > > > > Apache Concerted
> >> >> > > > > >
> >> >> > > > >
> >> >> > > >
> >> >> > >
> >> >> >
> >> >>
> >> >>
> >> >> --
> >> >> Best regards,
> >> >> Andrey V. Mashenkov
> >> >>
> >> >
> >>
> >>
> >> --
> >>
> >> Best regards,
> >> Ivan Pavlukhin
> >>
> >>
> >
> > --
> > Best regards,
> > Andrey V. Mashenkov
> >
>
>
> --
>
> Best regards,
> Ivan Pavlukhin
>
>

-- 
Best regards,
Andrey V. Mashenkov

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message