Re: Concurrency-interest Digest, Vol 163, Issue 1

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Concurrency-interest Digest, Vol 163, Issue 1

JSR166 Concurrency mailing list
You can define such a function yourself:
public static CompletableFuture<ReturnType> exceptionallyAsync(
CompletableFuture<ReturnType> cf,
Function<Throwable, ReturnType> handleFunction,
Executor executor
) {
CompletableFuture<ReturnType> resFuture = new CompletableFuture<>();
cf.whenComplete((result, exC) -> {
if (exC != null) {
CompletableFuture.runAsync(() -> {
ReturnType valEx = handleFunction.apply(exC);
resFuture.complete(valEx);
}, executor);
} else {
resFuture.complete(result);
}
});
return resFuture;
}
Usage:
CompletableFuture<ReturnType> resFuture = exceptionallyAsync(someCompletableFuture, exc->new ReturnType(exc), ForkJoinPool.commonPool());

thanks,
Alexei


On Sun, 2 Sep 2018 at 23:01, <[hidden email]> wrote:
Send Concurrency-interest mailing list submissions to
        [hidden email]

To subscribe or unsubscribe via the World Wide Web, visit
        http://cs.oswego.edu/mailman/listinfo/concurrency-interest
or, via email, send a message with subject or body 'help' to
        [hidden email]

You can reach the person managing the list at
        [hidden email]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Concurrency-interest digest..."


Today's Topics:

   1. CompletableFuture.exceptionallyAsync or   handleCompose
      (Peter Levart)


----------------------------------------------------------------------

Message: 1
Date: Sun, 2 Sep 2018 17:46:43 +0200
From: Peter Levart <[hidden email]>
To: concurrency-interest <[hidden email]>
Subject: [concurrency-interest] CompletableFuture.exceptionallyAsync
        or      handleCompose
Message-ID: <[hidden email]>
Content-Type: text/plain; charset="utf-8"; Format="flowed"

Hello,

Recently I needed to code a completion stage that would asynchronously
handle an exceptional completion of previous stage but in case of normal
completion of previous stage didn't introduce another asynchronous step.
I couldn't find a simple solution with CompletableFuture. Either of the
following two methods were missing:

     public CompletableFuture<T> exceptionallyAsync(Function<Throwable,
? extends T> fn)

...with an overload taking Executor. These would be the async
counterparts of existing "exceptionaly" method.

Similar functionality could be achieved with the following method:

     public <U> CompletableFuture<U> handleCompose(BiFunction<? super T,
Throwable, ? extends CompletionStage<U>> fn)

...which would be a combination of the following two existing methods:

     public <U> CompletableFuture<U> handle(BiFunction<? super T,
Throwable, ? extends U> fn)
     public <U> CompletableFuture<U> thenCompose(Function<? super T, ?
extends CompletionStage<U>> fn)


The with handleCompose method one could simulate exceptionallyAsync by
returning a submitted but yet uncompleted CompletableFuture in case of
exceptional completion of previous stage, while returning a completed
CompletableFuture in case of normal completion.

The use case I'm trying to handle is using CompletionStage as a return
type of an asynchronous web service endpoint method. The thread that
completes the returned CF is a scarce resource (a single Kafka IO
thread). In case of normal completion I can hand such CompletableFuture
to web container as it dispatches the control from it to internal thread
pool when handling the response. But in case of exceptional completion,
I would like to employ special thread-pool to handle the exception as
this involves additional external communication.

Currently I'm using the following trick:

someCompletableFuture

             // tunnel exception as the normal result
             .handle((result, exception) -> exception != null ?
exception : result)

             .thenCompose(resultOrException -> {
                 if (resultOrException instanceof Throwable) {
                     return CompletableFuture.supplyAsync(() -> {
                         Throwable exc = (Throwable) resultOrException
                         // ...handle exc asynchronously...
                     });
                 } else {
                     // just pass return value synchronously
                     return CompletableFuture
                         .completedFuture((ReturnType) resultOrException);
                 }
             });


Has anyone else missed such method(s) on CompletableFuture too?

Regards, Peter

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20180902/deb3b851/attachment-0001.html>

------------------------------

Subject: Digest Footer

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


------------------------------

End of Concurrency-interest Digest, Vol 163, Issue 1
****************************************************

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Concurrency-interest Digest, Vol 163, Issue 1

JSR166 Concurrency mailing list
A production-quality version of exceptionallyAsync would have more error handling for the cases where runAsync or handleFunction threw, creating typically messy method bodies - a good reason for why exceptionallyAsync should be provided by CompletableFuture.

On Sun, Sep 2, 2018 at 10:41 AM, Alexei Kaigorodov via Concurrency-interest <[hidden email]> wrote:
You can define such a function yourself:
public static CompletableFuture<ReturnType> exceptionallyAsync(
CompletableFuture<ReturnType> cf,
Function<Throwable, ReturnType> handleFunction,
Executor executor
) {
CompletableFuture<ReturnType> resFuture = new CompletableFuture<>();
cf.whenComplete((result, exC) -> {
if (exC != null) {
CompletableFuture.runAsync(() -> {
ReturnType valEx = handleFunction.apply(exC);
resFuture.complete(valEx);
}, executor);
} else {
resFuture.complete(result);
}
});
return resFuture;
}
Usage:
CompletableFuture<ReturnType> resFuture = exceptionallyAsync(someCompletableFuture, exc->new ReturnType(exc), ForkJoinPool.commonPool());

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