@Override public boolean cancel(boolean mayInterruptIfRunning) { synchronized (lock) { if (attemptFutureCompletionListener == null) { // explicit retry future cancellation, most probably even before the first attempt started return super.cancel(mayInterruptIfRunning); } // will result in attempt triggered cancellation of the whole future via callback chain attemptFutureCompletionListener.attemptFuture.cancel(mayInterruptIfRunning); return isCancelled(); } }
/** * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for * any retriable operation to complete. The returned future is bounded to {@code this} executor * instance. * * @param callable the actual callable, which should be executed in a retriable context * @param context the context for this operation * @return retrying future facade */ @BetaApi("The surface for passing per operation state is not yet stable") @Override public RetryingFuture<ResponseT> createFuture( Callable<ResponseT> callable, RetryingContext context) { return new CallbackChainRetryingFuture<>(callable, retryAlgorithm, this, context); }
@Override public void setAttemptFuture(ApiFuture<ResponseT> attemptFuture) { if (isDone()) { return; } synchronized (lock) { if (isDone()) { return; } attemptFutureCompletionListener = new AttemptCompletionListener(attemptFuture); // Using direct addListener instead of ApiFutures.addCallback allows greatly reduce // layering. Also listener is more suitable here (as we don't really need two methods - // one for failure and one for success). attemptFuture.addListener(attemptFutureCompletionListener, MoreExecutors.directExecutor()); } }
/** * Creates a {@link RetryingFuture}, which is a facade, returned to the client code to wait for * any retriable operation to complete. The returned future is bounded to {@code this} executor * instance. * * @param callable the actual callable, which should be executed in a retriable context * @param context the context for this operation * @return retrying future facade */ @BetaApi("The surface for passing per operation state is not yet stable") @Override public RetryingFuture<ResponseT> createFuture( Callable<ResponseT> callable, RetryingContext context) { return new CallbackChainRetryingFuture<>(callable, retryAlgorithm, this, context); }
@Override public void setAttemptFuture(ApiFuture<ResponseT> attemptFuture) { if (isDone()) { return; } synchronized (lock) { if (isDone()) { return; } attemptFutureCompletionListener = new AttemptCompletionListener(attemptFuture); // Using direct addListener instead of ApiFutures.addCallback allows greatly reduce // layering. Also listener is more suitable here (as we don't really need two methods - // one for failure and one for success). attemptFuture.addListener(attemptFutureCompletionListener, MoreExecutors.directExecutor()); } }
@Override public boolean cancel(boolean mayInterruptIfRunning) { synchronized (lock) { if (attemptFutureCompletionListener == null) { // explicit retry future cancellation, most probably even before the first attempt started return super.cancel(mayInterruptIfRunning); } // will result in attempt triggered cancellation of the whole future via callback chain attemptFutureCompletionListener.attemptFuture.cancel(mayInterruptIfRunning); return isCancelled(); } }