Re: Counter-intuitive behavior of CompleteableFuture

Viktor Klang via Concurrency-interest <[email protected]> Thu, 20 May 2021 12:59:10 +0000
Newsgroups gmane.comp.java.jsr.166-concurrency
Message-ID <CANPzfU-Z9jWkexyegYLrhqGpO-4W7EfnzaGLgb7UFa+2YTFsGg@mail.gmail.com>
A solution which has been used very successfully in Scala is the
distinction between Promise (write a single value 0..1 times) and Future
(read a single value 0..N times), which means that only the thread who owns
a reference to the Promise can write values, which means that Futures can
be freely shared since consumers cannot manipulate the result "further up
the chain".

You can achieve something similar in Java by separating CompletableFuture
from CompletionStage.

public static void main(String[] args) {
    CompletableFuture<String> initial = new CompletableFuture<>();

    CompletionStage<String> withSteps = initial
            .thenApply(s -> {
                System.out.println("STEP1: " + s);
                return s;
            })
            .thenApply(s -> {
                System.out.println("STEP2: " + s);
                return s;
            });

    CompletionStage<String> timeout = withSteps;

    timeout.whenComplete((s, throwable) ->
System.out.println("TIMEOUT: " + throwable));

    timeout.completeExceptionally(new RuntimeException("TIMEOUT")); <---
now won't compile
    initial.complete("SUCCESS");
}


On Thu, May 20, 2021 at 12:50 PM Michał Górniewski via Concurrency-interest
<[email protected]> wrote:

> What bothers me here is API of CompletableFuture itself, e.g:
>
> public CompletableFuture<ProcessingOutput>
> executeProcessing(Function<Path, ProcessingOutput> processor) {
>     Path data = prepareData();
>     return CompletableFuture.supplyAsync(() -> processor.apply(data),
> processingExecutor)
>             .whenComplete((o, ex) -> cleanup(data));
> }
>
> Callers of this method may just break cleanup, without even knowing
> about this, but simply calling complete() on returned CF. But it seems
> that nothing can be done about it.
>
> czw., 20 maj 2021 o 14:40 Benjamin Manes <[email protected]> napisał(a):
> >
> > The timeout is applied to the STEP2 future which completes it
> exceptionally. This causes it to not run the mapping function for a result,
> as it was completed prior to that being triggered. You can use copy() to
> decouple the source from the timeout if you want both to complete; e.g.
> cache a long running value but fail a consumer if taking to long.
> >
> > On Thu, May 20, 2021 at 5:31 AM Michał Górniewski via
> Concurrency-interest <[email protected]> wrote:
> >>
> >> With following code:
> >>
> >> ------------------------------
> >> public static void main(String[] args) {
> >>     CompletableFuture<String> initial = new CompletableFuture<>();
> >>
> >>     CompletableFuture<String> withSteps = initial
> >>             .thenApply(s -> {
> >>                 System.out.println("STEP1: " + s);
> >>                 return s;
> >>             })
> >>             .thenApply(s -> {
> >>                 System.out.println("STEP2: " + s);
> >>                 return s;
> >>             });
> >>
> >>     CompletableFuture<String> timeout = withSteps;
> >>
> >>     timeout.whenComplete((s, throwable) ->
> >> System.out.println("TIMEOUT: " + throwable));
> >>
> >>     timeout.completeExceptionally(new RuntimeException("TIMEOUT"));
> >>     initial.complete("SUCCESS");
> >> }
> >> ------------------------------
> >>
> >> I got output like this:
> >>
> >> ------------------------------
> >> TIMEOUT: java.lang.RuntimeException: TIMEOUT
> >> STEP1: SUCCESS
> >> ------------------------------
> >>
> >> I don't understand why "STEP2" is not executed in this case. Is this
> expected?
> >> For me this API is confusing and may create issues like this:
> >> https://github.com/resilience4j/resilience4j/issues/1427
> >>
> >> Thanks,
> >> Michał Górniewski
> >> _______________________________________________
> >> Concurrency-interest mailing list
> >> [email protected]
> >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> _______________________________________________
> Concurrency-interest mailing list
> [email protected]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>


-- 
Cheers,
√

_______________________________________________
Concurrency-interest mailing list
[email protected]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest