| /* |
| * Copyright (C) 2006 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.google.common.util.concurrent; |
| |
| import com.google.common.annotations.Beta; |
| import com.google.common.annotations.GwtCompatible; |
| import com.google.common.annotations.GwtIncompatible; |
| import com.google.common.base.Function; |
| import com.google.errorprone.annotations.CanIgnoreReturnValue; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.ScheduledExecutorService; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| |
| /** |
| * A {@link ListenableFuture} that supports fluent chains of operations. For example: |
| * |
| * <pre>{@code |
| * ListenableFuture<Boolean> adminIsLoggedIn = |
| * FluentFuture.from(usersDatabase.getAdminUser()) |
| * .transform(User::getId, directExecutor()) |
| * .transform(ActivityService::isLoggedIn, threadPool) |
| * .catching(RpcException.class, e -> false, directExecutor()); |
| * }</pre> |
| * |
| * <h3>Alternatives</h3> |
| * |
| * <h4>Frameworks</h4> |
| * |
| * <p>When chaining together a graph of asynchronous operations, you will often find it easier to |
| * use a framework. Frameworks automate the process, often adding features like monitoring, |
| * debugging, and cancellation. Examples of frameworks include: |
| * |
| * <ul> |
| * <li><a href="http://google.github.io/dagger/producers.html">Dagger Producers</a> |
| * </ul> |
| * |
| * <h4>{@link java.util.concurrent.CompletableFuture} / {@link java.util.concurrent.CompletionStage} |
| * </h4> |
| * |
| * <p>Users of {@code CompletableFuture} will likely want to continue using {@code |
| * CompletableFuture}. {@code FluentFuture} is targeted at people who use {@code ListenableFuture}, |
| * who can't use Java 8, or who want an API more focused than {@code CompletableFuture}. (If you |
| * need to adapt between {@code CompletableFuture} and {@code ListenableFuture}, consider <a |
| * href="https://github.com/lukas-krecan/future-converter">Future Converter</a>.) |
| * |
| * <h3>Extension</h3> |
| * |
| * If you want a class like {@code FluentFuture} but with extra methods, we recommend declaring your |
| * own subclass of {@link ListenableFuture}, complete with a method like {@link #from} to adapt an |
| * existing {@code ListenableFuture}, implemented atop a {@link ForwardingListenableFuture} that |
| * forwards to that future and adds the desired methods. |
| * |
| * @since 23.0 |
| */ |
| @Beta |
| @GwtCompatible(emulated = true) |
| public abstract class FluentFuture<V> extends GwtFluentFutureCatchingSpecialization<V> { |
| |
| /** |
| * A less abstract subclass of AbstractFuture. This can be used to optimize setFuture by ensuring |
| * that {@link #get} calls exactly the implementation of {@link AbstractFuture#get}. |
| */ |
| abstract static class TrustedFuture<V> extends FluentFuture<V> |
| implements AbstractFuture.Trusted<V> { |
| @CanIgnoreReturnValue |
| @Override |
| public final V get() throws InterruptedException, ExecutionException { |
| return super.get(); |
| } |
| |
| @CanIgnoreReturnValue |
| @Override |
| public final V get(long timeout, TimeUnit unit) |
| throws InterruptedException, ExecutionException, TimeoutException { |
| return super.get(timeout, unit); |
| } |
| |
| @Override |
| public final boolean isDone() { |
| return super.isDone(); |
| } |
| |
| @Override |
| public final boolean isCancelled() { |
| return super.isCancelled(); |
| } |
| |
| @Override |
| public final void addListener(Runnable listener, Executor executor) { |
| super.addListener(listener, executor); |
| } |
| |
| @CanIgnoreReturnValue |
| @Override |
| public final boolean cancel(boolean mayInterruptIfRunning) { |
| return super.cancel(mayInterruptIfRunning); |
| } |
| } |
| |
| FluentFuture() {} |
| |
| /** |
| * Converts the given {@code ListenableFuture} to an equivalent {@code FluentFuture}. |
| * |
| * <p>If the given {@code ListenableFuture} is already a {@code FluentFuture}, it is returned |
| * directly. If not, it is wrapped in a {@code FluentFuture} that delegates all calls to the |
| * original {@code ListenableFuture}. |
| */ |
| public static <V> FluentFuture<V> from(ListenableFuture<V> future) { |
| return future instanceof FluentFuture |
| ? (FluentFuture<V>) future |
| : new ForwardingFluentFuture<V>(future); |
| } |
| |
| /** |
| * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code |
| * Future} fails with the given {@code exceptionType}, from the result provided by the {@code |
| * fallback}. {@link Function#apply} is not invoked until the primary input has failed, so if the |
| * primary input succeeds, it is never invoked. If, during the invocation of {@code fallback}, an |
| * exception is thrown, this exception is used as the result of the output {@code Future}. |
| * |
| * <p>Usage example: |
| * |
| * <pre>{@code |
| * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch |
| * // counters. |
| * ListenableFuture<Integer> faultTolerantFuture = |
| * fetchCounters().catching(FetchException.class, x -> 0, directExecutor()); |
| * }</pre> |
| * |
| * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See |
| * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight |
| * listeners are also applicable to heavyweight functions passed to this method. |
| * |
| * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It |
| * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle} |
| * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link |
| * #transform}. |
| * |
| * @param exceptionType the exception type that triggers use of {@code fallback}. The exception |
| * type is matched against the input's exception. "The input's exception" means the cause of |
| * the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a |
| * different kind of exception, that exception itself. To avoid hiding bugs and other |
| * unrecoverable errors, callers should prefer more specific types, avoiding {@code |
| * Throwable.class} in particular. |
| * @param fallback the {@link Function} to be called if the input fails with the expected |
| * exception type. The function's argument is the input's exception. "The input's exception" |
| * means the cause of the {@link ExecutionException} thrown by {@code this.get()} or, if |
| * {@code get()} throws a different kind of exception, that exception itself. |
| * @param executor the executor that runs {@code fallback} if the input fails |
| */ |
| @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") |
| public final <X extends Throwable> FluentFuture<V> catching( |
| Class<X> exceptionType, Function<? super X, ? extends V> fallback, Executor executor) { |
| return (FluentFuture<V>) Futures.catching(this, exceptionType, fallback, executor); |
| } |
| |
| /** |
| * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code |
| * Future} fails with the given {@code exceptionType}, from the result provided by the {@code |
| * fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has failed, so if |
| * the primary input succeeds, it is never invoked. If, during the invocation of {@code fallback}, |
| * an exception is thrown, this exception is used as the result of the output {@code Future}. |
| * |
| * <p>Usage examples: |
| * |
| * <pre>{@code |
| * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch |
| * // counters. |
| * ListenableFuture<Integer> faultTolerantFuture = |
| * fetchCounters().catchingAsync( |
| * FetchException.class, x -> immediateFuture(0), directExecutor()); |
| * }</pre> |
| * |
| * <p>The fallback can also choose to propagate the original exception when desired: |
| * |
| * <pre>{@code |
| * // Falling back to a zero counter only in case the exception was a |
| * // TimeoutException. |
| * ListenableFuture<Integer> faultTolerantFuture = |
| * fetchCounters().catchingAsync( |
| * FetchException.class, |
| * e -> { |
| * if (omitDataOnFetchFailure) { |
| * return immediateFuture(0); |
| * } |
| * throw e; |
| * }, |
| * directExecutor()); |
| * }</pre> |
| * |
| * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See |
| * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight |
| * listeners are also applicable to heavyweight functions passed to this method. (Specifically, |
| * {@code directExecutor} functions should avoid heavyweight operations inside {@code |
| * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for |
| * completing the returned {@code Future}.) |
| * |
| * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It |
| * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle} |
| * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link |
| * #transform}. |
| * |
| * @param exceptionType the exception type that triggers use of {@code fallback}. The exception |
| * type is matched against the input's exception. "The input's exception" means the cause of |
| * the {@link ExecutionException} thrown by {@code this.get()} or, if {@code get()} throws a |
| * different kind of exception, that exception itself. To avoid hiding bugs and other |
| * unrecoverable errors, callers should prefer more specific types, avoiding {@code |
| * Throwable.class} in particular. |
| * @param fallback the {@link AsyncFunction} to be called if the input fails with the expected |
| * exception type. The function's argument is the input's exception. "The input's exception" |
| * means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if |
| * {@code get()} throws a different kind of exception, that exception itself. |
| * @param executor the executor that runs {@code fallback} if the input fails |
| */ |
| @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class") |
| public final <X extends Throwable> FluentFuture<V> catchingAsync( |
| Class<X> exceptionType, AsyncFunction<? super X, ? extends V> fallback, Executor executor) { |
| return (FluentFuture<V>) Futures.catchingAsync(this, exceptionType, fallback, executor); |
| } |
| |
| /** |
| * Returns a future that delegates to this future but will finish early (via a {@link |
| * TimeoutException} wrapped in an {@link ExecutionException}) if the specified timeout expires. |
| * If the timeout expires, not only will the output future finish, but also the input future |
| * ({@code this}) will be cancelled and interrupted. |
| * |
| * @param timeout when to time out the future |
| * @param unit the time unit of the time parameter |
| * @param scheduledExecutor The executor service to enforce the timeout. |
| */ |
| @GwtIncompatible // ScheduledExecutorService |
| @SuppressWarnings("GoodTime") // should accept a java.time.Duration |
| public final FluentFuture<V> withTimeout( |
| long timeout, TimeUnit unit, ScheduledExecutorService scheduledExecutor) { |
| return (FluentFuture<V>) Futures.withTimeout(this, timeout, unit, scheduledExecutor); |
| } |
| |
| /** |
| * Returns a new {@code Future} whose result is asynchronously derived from the result of this |
| * {@code Future}. If the input {@code Future} fails, the returned {@code Future} fails with the |
| * same exception (and the function is not invoked). |
| * |
| * <p>More precisely, the returned {@code Future} takes its result from a {@code Future} produced |
| * by applying the given {@code AsyncFunction} to the result of the original {@code Future}. |
| * Example usage: |
| * |
| * <pre>{@code |
| * FluentFuture<RowKey> rowKeyFuture = FluentFuture.from(indexService.lookUp(query)); |
| * ListenableFuture<QueryResult> queryFuture = |
| * rowKeyFuture.transformAsync(dataService::readFuture, executor); |
| * }</pre> |
| * |
| * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See |
| * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight |
| * listeners are also applicable to heavyweight functions passed to this method. (Specifically, |
| * {@code directExecutor} functions should avoid heavyweight operations inside {@code |
| * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for |
| * completing the returned {@code Future}.) |
| * |
| * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the |
| * input future and that of the future returned by the chain function. That is, if the returned |
| * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the |
| * other two is cancelled, the returned {@code Future} will receive a callback in which it will |
| * attempt to cancel itself. |
| * |
| * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#thenCompose} and |
| * {@link java.util.concurrent.CompletableFuture#thenComposeAsync}. It can also serve some of the |
| * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link |
| * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}. |
| * |
| * @param function A function to transform the result of this future to the result of the output |
| * future |
| * @param executor Executor to run the function in. |
| * @return A future that holds result of the function (if the input succeeded) or the original |
| * input's failure (if not) |
| */ |
| public final <T> FluentFuture<T> transformAsync( |
| AsyncFunction<? super V, T> function, Executor executor) { |
| return (FluentFuture<T>) Futures.transformAsync(this, function, executor); |
| } |
| |
| /** |
| * Returns a new {@code Future} whose result is derived from the result of this {@code Future}. If |
| * this input {@code Future} fails, the returned {@code Future} fails with the same exception (and |
| * the function is not invoked). Example usage: |
| * |
| * <pre>{@code |
| * ListenableFuture<List<Row>> rowsFuture = |
| * queryFuture.transform(QueryResult::getRows, executor); |
| * }</pre> |
| * |
| * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See |
| * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight |
| * listeners are also applicable to heavyweight functions passed to this method. |
| * |
| * <p>The returned {@code Future} attempts to keep its cancellation state in sync with that of the |
| * input future. That is, if the returned {@code Future} is cancelled, it will attempt to cancel |
| * the input, and if the input is cancelled, the returned {@code Future} will receive a callback |
| * in which it will attempt to cancel itself. |
| * |
| * <p>An example use of this method is to convert a serializable object returned from an RPC into |
| * a POJO. |
| * |
| * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#thenApply} and |
| * {@link java.util.concurrent.CompletableFuture#thenApplyAsync}. It can also serve some of the |
| * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link |
| * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}. |
| * |
| * @param function A Function to transform the results of this future to the results of the |
| * returned future. |
| * @param executor Executor to run the function in. |
| * @return A future that holds result of the transformation. |
| */ |
| public final <T> FluentFuture<T> transform(Function<? super V, T> function, Executor executor) { |
| return (FluentFuture<T>) Futures.transform(this, function, executor); |
| } |
| |
| /** |
| * Registers separate success and failure callbacks to be run when this {@code Future}'s |
| * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the |
| * computation is already complete, immediately. |
| * |
| * <p>The callback is run on {@code executor}. There is no guaranteed ordering of execution of |
| * callbacks, but any callback added through this method is guaranteed to be called once the |
| * computation is complete. |
| * |
| * <p>Example: |
| * |
| * <pre>{@code |
| * future.addCallback( |
| * new FutureCallback<QueryResult>() { |
| * public void onSuccess(QueryResult result) { |
| * storeInCache(result); |
| * } |
| * public void onFailure(Throwable t) { |
| * reportError(t); |
| * } |
| * }, executor); |
| * }</pre> |
| * |
| * <p>When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See |
| * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight |
| * listeners are also applicable to heavyweight callbacks passed to this method. |
| * |
| * <p>For a more general interface to attach a completion listener, see {@link #addListener}. |
| * |
| * <p>This method is similar to {@link java.util.concurrent.CompletableFuture#whenComplete} and |
| * {@link java.util.concurrent.CompletableFuture#whenCompleteAsync}. It also serves the use case |
| * of {@link java.util.concurrent.CompletableFuture#thenAccept} and {@link |
| * java.util.concurrent.CompletableFuture#thenAcceptAsync}. |
| * |
| * @param callback The callback to invoke when this {@code Future} is completed. |
| * @param executor The executor to run {@code callback} when the future completes. |
| */ |
| public final void addCallback(FutureCallback<? super V> callback, Executor executor) { |
| Futures.addCallback(this, callback, executor); |
| } |
| } |