org.testifyproject.failsafe.AsyncFailsafe Maven / Gradle / Ivy
Show all versions of core Show documentation
/*
* Copyright 2016 the original author or 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 org.testifyproject.failsafe;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.testifyproject.failsafe.Functions.AsyncCallableWrapper;
import org.testifyproject.failsafe.function.AsyncCallable;
import org.testifyproject.failsafe.function.AsyncRunnable;
import org.testifyproject.failsafe.function.CheckedBiFunction;
import org.testifyproject.failsafe.function.CheckedRunnable;
import org.testifyproject.failsafe.function.ContextualCallable;
import org.testifyproject.failsafe.function.ContextualRunnable;
import org.testifyproject.failsafe.util.concurrent.Scheduler;
/**
* Performs asynchronous executions with failures handled according to a configured {@link #with(RetryPolicy) retry
* policy}, {@link #with(CircuitBreaker) circuit breaker} and
* {@link #withFallback(org.testifyproject.failsafe.function.CheckedBiFunction) fallback}.
*
* @author Jonathan Halterman
* @param listener result type
*/
public class AsyncFailsafe extends AsyncFailsafeConfig> {
AsyncFailsafe(FailsafeConfig config, Scheduler scheduler) {
super(config, scheduler);
}
/**
* Executes the {@code callable} asynchronously until the resulting future is successfully completed or the configured
* {@link RetryPolicy} is exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed exceptionally with
* {@link CircuitBreakerOpenException}.
*
* Supported on Java 8 and above.
*
* @throws NullPointerException if the {@code callable} is null
*/
public java.util.concurrent.CompletableFuture future(
Callable> callable) {
return call(Functions.asyncOfFuture(callable));
}
/**
* Executes the {@code callable} asynchronously until the resulting future is successfully completed or the configured
* {@link RetryPolicy} is exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed exceptionally with
* {@link CircuitBreakerOpenException}.
*
* Supported on Java 8 and above.
*
* @throws NullPointerException if the {@code callable} is null
*/
public java.util.concurrent.CompletableFuture future(
ContextualCallable> callable) {
return call(Functions.asyncOfFuture(callable));
}
/**
* Executes the {@code callable} asynchronously until the resulting future is successfully completed or the configured
* {@link RetryPolicy} is exceeded. This method is intended for integration with asynchronous code. Retries must be
* manually scheduled via one of the {@code AsyncExecution.retry} methods.
*
* If a configured circuit breaker is open, the resulting future is completed exceptionally with
* {@link CircuitBreakerOpenException}.
*
* Supported on Java 8 and above.
*
* @throws NullPointerException if the {@code callable} is null
*/
public java.util.concurrent.CompletableFuture futureAsync(
AsyncCallable> callable) {
return call(Functions.asyncOfFuture(callable));
}
/**
* Executes the {@code callable} asynchronously until a successful result is returned or the configured
* {@link RetryPolicy} is exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code callable} is null
*/
public FailsafeFuture get(Callable callable) {
return call(Functions.asyncOf(callable), null);
}
/**
* Executes the {@code callable} asynchronously until a successful result is returned or the configured
* {@link RetryPolicy} is exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code callable} is null
*/
public FailsafeFuture get(ContextualCallable callable) {
return call(Functions.asyncOf(callable), null);
}
/**
* Executes the {@code callable} asynchronously until a successful result is returned or the configured
* {@link RetryPolicy} is exceeded. This method is intended for integration with asynchronous code. Retries must be
* manually scheduled via one of the {@code AsyncExecution.retry} methods.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code callable} is null
*/
public FailsafeFuture getAsync(AsyncCallable callable) {
return call(Functions.asyncOf(callable), null);
}
/**
* Executes the {@code runnable} asynchronously until successful or until the configured {@link RetryPolicy} is
* exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code runnable} is null
*/
public FailsafeFuture run(CheckedRunnable runnable) {
return call(Functions. asyncOf(runnable), null);
}
/**
* Executes the {@code runnable} asynchronously until successful or until the configured {@link RetryPolicy} is
* exceeded.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code runnable} is null
*/
public FailsafeFuture run(ContextualRunnable runnable) {
return call(Functions. asyncOf(runnable), null);
}
/**
* Executes the {@code runnable} asynchronously until successful or until the configured {@link RetryPolicy} is
* exceeded. This method is intended for integration with asynchronous code. Retries must be manually scheduled via
* one of the {@code AsyncExecution.retry} methods.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if the {@code runnable} is null
*/
public FailsafeFuture runAsync(AsyncRunnable runnable) {
return call(Functions. asyncOf(runnable), null);
}
/**
* Calls the asynchronous {@code callable} via the configured Scheduler, performing retries according to the
* configured RetryPolicy, and returns a CompletableFuture.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if any argument is null
*/
@SuppressWarnings("unchecked")
private java.util.concurrent.CompletableFuture call(AsyncCallableWrapper callable) {
FailsafeFuture future = new FailsafeFuture((FailsafeConfig) this);
java.util.concurrent.CompletableFuture response = org.testifyproject.failsafe.internal.util.CancellableFuture.of(future);
future.inject(response);
call(callable, future);
return response;
}
/**
* Calls the asynchronous {@code callable} via the configured Scheduler, performing retries according to the
* configured RetryPolicy.
*
* If a configured circuit breaker is open, the resulting future is completed with
* {@link CircuitBreakerOpenException}.
*
* @throws NullPointerException if any argument is null
*/
@SuppressWarnings("unchecked")
private FailsafeFuture call(AsyncCallableWrapper callable, FailsafeFuture future) {
if (future == null)
future = new FailsafeFuture((FailsafeConfig) this);
if (circuitBreaker != null && !circuitBreaker.allowsExecution()) {
CircuitBreakerOpenException e = new CircuitBreakerOpenException();
future.complete(null, e, (CheckedBiFunction) fallback, false);
return future;
}
AsyncExecution execution = new AsyncExecution(callable, scheduler, future, (FailsafeConfig