All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.smallrye.faulttolerance.api.FaultTolerance Maven / Gradle / Ivy

There is a newer version: 6.4.1
Show newest version
package io.smallrye.faulttolerance.api;

import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.eclipse.microprofile.faulttolerance.Asynchronous;
import org.eclipse.microprofile.faulttolerance.Bulkhead;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;

import io.smallrye.common.annotation.Experimental;

/**
 * Allows guarding an action with various fault tolerance strategies: bulkhead, circuit breaker, fallback, rate limit,
 * retry, and timeout. Synchronous as well as asynchronous actions may be guarded, asynchronous actions may optionally
 * be offloaded to another thread. The only supported type for asynchronous actions is {@link CompletionStage}.
 * 

* An instance of this interface represents a configured set of fault tolerance strategies. It can be used to * guard a {@link #call(Callable) Callable}, {@link #get(Supplier) Supplier} or {@link #run(Runnable) Runnable} * invocation, or adapt an unguarded {@link #adaptCallable(Callable) Callable}, {@link #adaptSupplier(Supplier) Supplier} * or {@link #adaptRunnable(Runnable) Runnable} to a guarded one. *

* The {@code create*} and {@code createAsync*} methods return a builder that allows configuring all fault tolerance * strategies. Order of builder method invocations does not matter, the fault tolerance strategies are always applied * in a predefined order: fallback > retry > circuit breaker > rate limit > timeout > bulkhead > * thread offload > guarded action. *

* Two styles of usage are possible. The {@link #createCallable(Callable)} and {@link #createAsyncCallable(Callable)} * methods return a builder that, at the end, returns a {@code Callable}. This is convenient in case you only want to * guard a single action (which is possibly invoked multiple times). Similar methods exist for the {@code Supplier} * and {@code Runnable} types. *

* The {@link #create()} and {@link #createAsync()} methods return a builder that, at the end, returns * a {@code FaultTolerance} instance, which is useful when you need to guard multiple actions with the same set * of fault tolerance strategies. Note that bulkheads, circuit breakers and rate limits are stateful, so there's * a big difference between guarding multiple actions using the same {@code FaultTolerance} object and using a separate * {@code FaultTolerance} object for each action. Using a single {@code FaultTolerance} instance to guard multiple * actions means that a single bulkhead, circuit breaker and/or rate limit will be shared among all those actions. *

* This API is essentially a programmatic equivalent to the declarative, annotation-based API of MicroProfile Fault * Tolerance and SmallRye Fault Tolerance. It shares the set of fault tolerance strategies, their invocation order * and behavior, their configuration properties, etc. Notable differences are: *

    *
  • asynchronous actions of type {@link Future} are not supported;
  • *
  • the fallback, circuit breaker and retry strategies always inspect the cause chain of exceptions, * following the behavior of SmallRye Fault Tolerance in the non-compatible mode.
  • *
* * @param type of value of the guarded action */ @Experimental("first attempt at providing programmatic API") public interface FaultTolerance { /** * Returns a {@link CircuitBreakerMaintenance} instance that provides maintenance access to existing * circuit breakers. */ static CircuitBreakerMaintenance circuitBreakerMaintenance() { return FaultToleranceSpiAccess.get().circuitBreakerMaintenance(); } /** * Returns a builder that, at the end, returns a {@link Callable} guarding the given {@code action}. * The {@code action} is synchronous and is always executed on the original thread. */ static Builder> createCallable(Callable action) { return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptCallable(action)); } /** * Returns a builder that, at the end, returns a {@link Supplier} guarding the given {@code action}. * The {@code action} is synchronous and is always executed on the original thread. */ static Builder> createSupplier(Supplier action) { return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptSupplier(action)); } /** * Returns a builder that, at the end, returns a {@link Runnable} guarding the given {@code action}. * The {@code action} is synchronous and is always executed on the original thread. */ static Builder createRunnable(Runnable action) { return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptRunnable(action)); } /** * Returns a builder that, at the end, returns a {@link FaultTolerance} object representing a set of configured * fault tolerance strategies. It can be used to execute synchronous actions using {@link #call(Callable)}, * {@link #get(Supplier)} or {@link #run(Runnable)}. *

* This method usually has to be called with an explicitly provided type argument. For example: * {@code FaultTolerance.<String>create()}. */ static Builder> create() { return FaultToleranceSpiAccess.get().newBuilder(Function.identity()); } /** * Returns a builder that, at the end, returns a {@link Callable} guarding the given {@code action}. * The {@code action} is asynchronous and may be offloaded to another thread. */ static Builder, Callable>> createAsyncCallable( Callable> action) { return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptCallable(action)); } /** * Returns a builder that, at the end, returns a {@link Supplier} guarding the given {@code action}. * The {@code action} is asynchronous and may be offloaded to another thread. */ static Builder, Supplier>> createAsyncSupplier( Supplier> action) { return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptSupplier(action)); } /** * Returns a builder that, at the end, returns a {@link Runnable} guarding the given {@code action}. * The {@code action} is asynchronous and may be offloaded to another thread. */ static Builder, Runnable> createAsyncRunnable(Runnable action) { return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptRunnable(action)); } /** * Returns a builder that, at the end, returns a {@link FaultTolerance} object representing a set of configured * fault tolerance strategies. It can be used to execute asynchronous actions using {@link #call(Callable)}, * {@link #get(Supplier)} or {@link #run(Runnable)}. *

* This method usually has to be called with an explicitly provided type argument. For example: * {@code FaultTolerance.<String>createAsync()}. */ static Builder, FaultTolerance>> createAsync() { return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, Function.identity()); } /** * Calls given {@code action} and guards the call by this configured set of fault tolerance strategies. * If this {@code FaultTolerance} instance was created using {@link #create()}, the action is synchronous * and is always executed on the same thread that calls this method. If this {@code FaultTolerance} instance * was created using {@link #createAsync()}, the action is asynchronous and may be offloaded to another thread * depending on how the builder was configured. */ T call(Callable action) throws Exception; /** * Calls given {@code action} and guards the call by this configured set of fault tolerance strategies. * If this {@code FaultTolerance} instance was created using {@code create*}, the action is synchronous * and is always executed on the same thread that calls this method. If this {@code FaultTolerance} instance * was created using {@code createAsync*}, the action is asynchronous and may be offloaded to another thread * depending on how the builder was configured. */ default T get(Supplier action) { try { return call(action::get); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } /** * Calls given {@code action} and guards the call by this configured set of fault tolerance strategies. * If this {@code FaultTolerance} instance was created using {@link #create()}, the action is synchronous * and is always executed on the same thread that calls this method. If this {@code FaultTolerance} instance * was created using {@link #createAsync()}, the action is asynchronous and may be offloaded to another thread * depending on how the builder was configured. */ default void run(Runnable action) { try { call(() -> { action.run(); return null; }); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } /** * Adapts given {@code action} to an action guarded by this configured set of fault tolerance strategies. * Useful when the action has to be called multiple times. *

* Equivalent to {@code () -> call(action)}. * * @see #call(Callable) */ default Callable adaptCallable(Callable action) { return () -> call(action); } /** * Adapts given {@code action} to an action guarded by this configured set of fault tolerance strategies. * Useful when the action has to be called multiple times. *

* Equivalent to {@code () -> get(action)}. * * @see #get(Supplier) */ default Supplier adaptSupplier(Supplier action) { return () -> get(action); } /** * Adapts given {@code action} to an action guarded by this configured set of fault tolerance strategies. * Useful when the action has to be called multiple times. *

* Equivalent to {@code () -> run(action)}. * * @see #run(Runnable) */ default Runnable adaptRunnable(Runnable action) { return () -> run(action); } /** * A builder for configuring fault tolerance strategies. A fault tolerance strategy is included in the resulting * set if the corresponding {@code with[Strategy]} method is called. Each strategy has its own builder to configure * the necessary attributes, and each such builder has a {@code done()} method that returns back to this builder. *

* In general, all builders in this API accept multiple invocations of the same method, but only the last * invocation is meaningful. Any previous invocations are forgotten. * * @param type of value of the guarded action * @param type of result of this builder, depends on how this builder was created */ interface Builder { /** * Assigns a description to the resulting set of configured fault tolerance strategies. The description * is used in logging messages and exception messages. *

* The description may be an arbitrary string. Duplicates are permitted. *

* If no description is set, a random UUID is used. * * @param value a description, must not be {@code null} * @return this fault tolerance builder */ Builder withDescription(String value); /** * Adds a bulkhead strategy. In this API, bulkhead is a simple concurrency limiter. * * @return a builder to configure the bulkhead strategy * @see Bulkhead @Bulkhead */ BulkheadBuilder withBulkhead(); /** * Adds a circuit breaker strategy. * * @return a builder to configure the circuit breaker strategy * @see CircuitBreaker @CircuitBreaker */ CircuitBreakerBuilder withCircuitBreaker(); /** * Adds a fallback strategy. * * @return a builder to configure the fallback strategy * @see Fallback @Fallback */ FallbackBuilder withFallback(); /** * Adds a rate limit strategy. * * @return a builder to configure the rate limit strategy * @see RateLimit @RateLimit */ RateLimitBuilder withRateLimit(); /** * Adds a retry strategy. Retry uses constant backoff between attempts by default, * but may be configured to use exponential backoff, Fibonacci backoff, or custom backoff. * * @return a builder to configure the retry strategy * @see Retry @Retry */ RetryBuilder withRetry(); /** * Adds a timeout strategy. * * @return a builder to configure the timeout strategy * @see Timeout @Timeout */ TimeoutBuilder withTimeout(); /** * Configures whether the guarded action should be offloaded to another thread. This is only possible * for asynchronous actions. If this builder was not created using {@code createAsync}, this method * throws an exception. * * @param value whether the guarded action should be offloaded to another thread * @return this fault tolerance builder * @see Asynchronous @Asynchronous * @see AsynchronousNonBlocking @AsynchronousNonBlocking */ Builder withThreadOffload(boolean value); /** * Returns a ready-to-use instance of {@code FaultTolerance} or guarded {@code Callable}, depending on * how this builder was created. */ R build(); /** * Syntactic sugar for calling the builder methods conditionally without breaking the invocation chain. * For example: * * *

{@code
         * FaultTolerance.create(this::doSomething)
         *     .withFallback() ... .done()
         *     .with(builder -> {
         *         if (useTimeout) {
         *             builder.withTimeout() ... .done();
         *         }
         *     })
         *     .build();
         * }
* * * @param consumer block of code to execute with this builder * @return this fault tolerance builder */ default Builder with(Consumer> consumer) { consumer.accept(this); return this; } /** * Configures a bulkhead. * * @see Bulkhead @Bulkhead */ interface BulkheadBuilder { /** * Sets the concurrency limit the bulkhead will enforce. Defaults to 10. * * @param value the concurrency limit, must be >= 1 * @return this bulkhead builder */ BulkheadBuilder limit(int value); /** * Sets the maximum size of the bulkhead queue. Defaults to 10. *

* May only be called if the builder configures fault tolerance for asynchronous actions. In other words, * if the builder was not created using {@code createAsync}, this method throws an exception. * * @param value the queue size, must be >= 1 * @return this bulkhead builder */ BulkheadBuilder queueSize(int value); /** * Sets a callback that will be invoked when this bulkhead accepts an invocation. * In case of asynchronous actions, accepting into bulkhead doesn't mean the action * is immediately invoked; the invocation is first put into a queue and may wait there. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the accepted callback, must not be {@code null} * @return this bulkhead builder */ BulkheadBuilder onAccepted(Runnable callback); /** * Sets a callback that will be invoked when this bulkhead rejects an invocation. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the rejected callback, must not be {@code null} * @return this bulkhead builder */ BulkheadBuilder onRejected(Runnable callback); /** * Sets a callback that will be invoked when a finished invocation leaves this bulkhead. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the finished callback, must not be {@code null} * @return this bulkhead builder */ BulkheadBuilder onFinished(Runnable callback); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default BulkheadBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a circuit breaker. * * @see CircuitBreaker @CircuitBreaker */ interface CircuitBreakerBuilder { /** * Sets the set of exception types considered failure. Defaults to all exceptions ({@code Throwable}). * * @param value collection of exception types, must not be {@code null} * @return this circuit breaker builder * @see CircuitBreaker#failOn() @CircuitBreaker.failOn */ CircuitBreakerBuilder failOn(Collection> value); /** * Equivalent to {@link #failOn(Collection) failOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this circuit breaker builder */ default CircuitBreakerBuilder failOn(Class value) { return failOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets the set of exception types considered success. Defaults to no exception (empty set). * * @param value collection of exception types, must not be {@code null} * @return this circuit breaker builder * @see CircuitBreaker#skipOn() @CircuitBreaker.skipOn */ CircuitBreakerBuilder skipOn(Collection> value); /** * Equivalent to {@link #skipOn(Collection) skipOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this circuit breaker builder */ default CircuitBreakerBuilder skipOn(Class value) { return skipOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets a predicate to determine when an exception should be considered failure * by the circuit breaker. This is a more general variant of {@link #failOn(Collection) failOn}. * Note that there is no generalized {@link #skipOn(Collection) skipOn}, because all exceptions * that do not match this predicate are implicitly considered success. *

* If this method is called, {@code failOn} and {@code skipOn} may not be called. * * @param value the predicate, must not be {@code null} * @return this circuit breaker builder */ CircuitBreakerBuilder when(Predicate value); /** * Sets the delay after which an open circuit moves to half-open. Defaults to 5 seconds. * * @param value the delay length, must be >= 0 * @param unit the delay unit, must not be {@code null} * @return this circuit breaker builder * @see CircuitBreaker#delay() @CircuitBreaker.delay * @see CircuitBreaker#delayUnit() @CircuitBreaker.delayUnit */ CircuitBreakerBuilder delay(long value, ChronoUnit unit); /** * Sets the size of the circuit breaker's rolling window. * * @param value the size of the circuit breaker's rolling window, must be >= 1 * @return this circuit breaker builder * @see CircuitBreaker#requestVolumeThreshold() @CircuitBreaker.requestVolumeThreshold */ CircuitBreakerBuilder requestVolumeThreshold(int value); /** * Sets the failure ratio that, once reached, will move a closed circuit breaker to open. Defaults to 0.5. * * @param value the failure ratio, must be >= 0 and <= 1 * @return this circuit breaker builder * @see CircuitBreaker#failureRatio() @CircuitBreaker.failureRatio */ CircuitBreakerBuilder failureRatio(double value); /** * Sets the number of successful executions that, once reached, will move a half-open circuit breaker * to closed. Defaults to 1. * * @param value the number of successful executions, must be >= 1 * @return this circuit breaker builder * @see CircuitBreaker#successThreshold() @CircuitBreaker.successThreshold */ CircuitBreakerBuilder successThreshold(int value); /** * Sets a circuit breaker name. Required to use the {@link CircuitBreakerMaintenance} methods. * Defaults to unnamed. It is an error to use the same name for multiple circuit breakers. *

* If a circuit breaker is not given a name, its state will not be affected * by {@link CircuitBreakerMaintenance#resetAll()}. This is unlike unnamed circuit breakers * declared using {@code @CircuitBreaker}, because there's a fixed number of circuit breakers * created using the declarative API, but a potentially unbounded number of circuit breakers * created using the programmatic API. In other words, automatically remembering all * circuit breakers created using the programmatic API would easily lead to a memory leak. * * @param value the circuit breaker name, must not be {@code null} * @return this circuit breaker builder * @see CircuitBreakerName @CircuitBreakerName */ CircuitBreakerBuilder name(String value); /** * Sets a callback that will be invoked upon each state change of this circuit breaker. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the state change callback, must not be {@code null} * @return this circuit breaker builder */ CircuitBreakerBuilder onStateChange(Consumer callback); /** * Sets a callback that will be invoked when this circuit breaker treats a finished invocation as success. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the success callback, must not be {@code null} * @return this circuit breaker builder */ CircuitBreakerBuilder onSuccess(Runnable callback); /** * Sets a callback that will be invoked when this circuit breaker treats a finished invocation as failure. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the failure callback, must not be {@code null} * @return this circuit breaker builder */ CircuitBreakerBuilder onFailure(Runnable callback); /** * Sets a callback that will be invoked when this circuit breaker prevents an invocation, because it is * in the open or half-open state. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the prevented callback, must not be {@code null} * @return this circuit breaker builder */ CircuitBreakerBuilder onPrevented(Runnable callback); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default CircuitBreakerBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a fallback. * * @see Fallback @Fallback */ interface FallbackBuilder { /** * Sets the fallback handler in the form of a fallback value {@link Supplier}. * * @param value the fallback value supplier, must not be {@code null} * @return this fallback builder */ FallbackBuilder handler(Supplier value); /** * Sets the fallback handler in the form of a {@link Function} that transforms the exception * to the fallback value. * * @param value the fallback value function, must not be {@code null} * @return this fallback builder */ FallbackBuilder handler(Function value); /** * Sets the set of exception types considered failure. Defaults to all exceptions ({@code Throwable}). * * @param value collection of exception types, must not be {@code null} * @return this fallback builder * @see Fallback#applyOn() @Fallback.applyOn */ FallbackBuilder applyOn(Collection> value); /** * Equivalent to {@link #applyOn(Collection) applyOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this fallback builder */ default FallbackBuilder applyOn(Class value) { return applyOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets the set of exception types considered success. Defaults to no exception (empty set). * * @param value collection of exception types, must not be {@code null} * @return this fallback builder * @see Fallback#skipOn() @Fallback.skipOn */ FallbackBuilder skipOn(Collection> value); /** * Equivalent to {@link #skipOn(Collection) skipOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this fallback builder */ default FallbackBuilder skipOn(Class value) { return skipOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets a predicate to determine when an exception should be considered failure * and fallback should be applied. This is a more general variant of {@link #applyOn(Collection) applyOn}. * Note that there is no generalized {@link #skipOn(Collection) skipOn}, because all exceptions * that do not match this predicate are implicitly considered success. *

* If this method is called, {@code applyOn} and {@code skipOn} may not be called. * * @param value the predicate, must not be {@code null} * @return this fallback builder */ FallbackBuilder when(Predicate value); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default FallbackBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a rate limit. * * @see RateLimit @RateLimit */ interface RateLimitBuilder { /** * Sets the maximum number of invocations in a time window. Defaults to 100. * * @param value maximum number of invocations in a time window, must be >= 1 * @return this rate limit builder */ RateLimitBuilder limit(int value); /** * Sets the time window length. Defaults to 1 second. * * @param value the time window size, must be >= 1 * @return this rate limit builder */ RateLimitBuilder window(long value, ChronoUnit unit); /** * Sets the minimum spacing between invocations. Defaults to 0. * * @param value the minimum spacing, must be >= 0 * @return this rate limit builder */ RateLimitBuilder minSpacing(long value, ChronoUnit unit); /** * Sets the type of time windows used for rate limiting. Defaults to {@link RateLimitType#FIXED}. * * @param value the time window type, must not be {@code null} * @return this rate limit builder */ RateLimitBuilder type(RateLimitType value); /** * Sets a callback that will be invoked when this rate limit permits an invocation. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the permitted callback, must not be {@code null} * @return this rate limit builder */ RateLimitBuilder onPermitted(Runnable callback); /** * Sets a callback that will be invoked when this rate limit rejects an invocation. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the rejected callback, must not be {@code null} * @return this rate limit builder */ RateLimitBuilder onRejected(Runnable callback); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default RateLimitBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a retry. * * @see Retry @Retry */ interface RetryBuilder { /** * Sets the maximum number of retries. Defaults to 3. * * @param value the maximum number of retries, must be >= -1. * @return this retry builder * @see Retry#maxRetries() @Retry.maxRetries */ RetryBuilder maxRetries(int value); /** * Sets the delay between retries. Defaults to 0. * * @param value the delay length, must be >= 0 * @param unit the delay unit, must not be {@code null} * @return this retry builder * @see Retry#delay() @Retry.delay * @see Retry#delayUnit() @Retry.delayUnit */ RetryBuilder delay(long value, ChronoUnit unit); /** * Sets the maximum duration of all invocations, including possible retries. Defaults to 3 minutes. * * @param value the maximum duration length, must be >= 0 * @param unit the maximum duration unit, must not be {@code null} * @return this retry builder * @see Retry#maxDuration() @Retry.maxDuration * @see Retry#durationUnit() @Retry.durationUnit */ RetryBuilder maxDuration(long value, ChronoUnit unit); /** * Sets the jitter bound. Random value in the range from {@code -jitter} to {@code +jitter} will be added * to the delay between retry attempts. Defaults to 200 millis. * * @param value the jitter bound length, must be >= 0 * @param unit the jitter bound unit, must not be {@code null} * @return this retry builder * @see Retry#jitter() @Retry.jitter * @see Retry#jitterDelayUnit() @Retry.jitterDelayUnit */ RetryBuilder jitter(long value, ChronoUnit unit); /** * Sets the set of exception types considered failure. Defaults to all exceptions ({@code Exception}). * * @param value collection of exception types, must not be {@code null} * @return this retry builder * @see Retry#retryOn() @Retry.retryOn */ RetryBuilder retryOn(Collection> value); /** * Equivalent to {@link #retryOn(Collection) retryOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this retry builder */ default RetryBuilder retryOn(Class value) { return retryOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets the set of exception types considered success. Defaults to no exception (empty set). * * @param value collection of exception types, must not be {@code null} * @return this retry builder * @see Retry#abortOn() @Retry.abortOn */ RetryBuilder abortOn(Collection> value); /** * Equivalent to {@link #abortOn(Collection) abortOn(Collections.singleton(value))}. * * @param value an exception class, must not be {@code null} * @return this retry builder */ default RetryBuilder abortOn(Class value) { return abortOn(Collections.singleton(Objects.requireNonNull(value))); } /** * Sets a predicate to determine when an exception should be considered failure * and retry should be attempted. This is a more general variant of {@link #retryOn(Collection) retryOn}. * Note that there is no generalized {@link #abortOn(Collection) abortOn}, because all exceptions * that do not match this predicate are implicitly considered success. *

* If this method is called, {@code retryOn} and {@code abortOn} may not be called. * * @param value the predicate, must not be {@code null} * @return this fallback builder */ RetryBuilder when(Predicate value); /** * Configures retry to use an exponential backoff instead of the default constant backoff. *

* Only one backoff strategy may be configured, so calling {@link #withFibonacciBackoff()} * or {@link #withCustomBackoff()} in addition to this method leads to an exception * during {@link #done()}. * * @return the exponential backoff builder * @see ExponentialBackoff @ExponentialBackoff */ ExponentialBackoffBuilder withExponentialBackoff(); /** * Configures retry to use a Fibonacci backoff instead of the default constant backoff. *

* Only one backoff strategy may be configured, so calling {@link #withExponentialBackoff()} * or {@link #withCustomBackoff()} in addition to this method leads to an exception * during {@link #done()}. * * @return the Fibonacci backoff builder * @see FibonacciBackoff @FibonacciBackoff */ FibonacciBackoffBuilder withFibonacciBackoff(); /** * Configures retry to use a custom backoff instead of the default constant backoff. *

* Only one backoff strategy may be configured, so calling {@link #withExponentialBackoff()} * or {@link #withFibonacciBackoff()} in addition to this method leads to an exception * during {@link #done()}. * * @return the custom backoff builder * @see CustomBackoff @CustomBackoff */ CustomBackoffBuilder withCustomBackoff(); /** * Sets a callback that will be invoked when a retry is attempted. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the retried callback, must not be {@code null} * @return this retry builder */ RetryBuilder onRetry(Runnable callback); /** * Sets a callback that will be invoked when this retry strategy treats a finished invocation as success, * regardless of whether a retry was attempted or not. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the retried callback, must not be {@code null} * @return this retry builder */ RetryBuilder onSuccess(Runnable callback); /** * Sets a callback that will be invoked when this retry strategy treats a finished invocation as failure, * and no more retries will be attempted. The failure may be caused by depleting the maximum * number of retries or the maximum duration, or by an exception that is not retryable. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the retried callback, must not be {@code null} * @return this retry builder */ RetryBuilder onFailure(Runnable callback); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default RetryBuilder with(Consumer> consumer) { consumer.accept(this); return this; } /** * Configures an exponential backoff for retry. * * @see ExponentialBackoff @ExponentialBackoff */ interface ExponentialBackoffBuilder { /** * Sets the multiplicative factor used to determine delay between retries. Defaults to 2. * * @param value the multiplicative factor, must be >= 1 * @return this exponential backoff builder * @see ExponentialBackoff#factor() @ExponentialBackoff.factor */ ExponentialBackoffBuilder factor(int value); /** * Sets the maximum delay between retries. Defaults to 1 minute. * * @param value the maximum delay, must be >= 0 * @param unit the maximum delay unit, must not be {@code null} * @return this exponential backoff builder * @see ExponentialBackoff#maxDelay() @ExponentialBackoff.maxDelay * @see ExponentialBackoff#maxDelayUnit() @ExponentialBackoff.maxDelayUnit */ ExponentialBackoffBuilder maxDelay(long value, ChronoUnit unit); /** * Returns the original retry builder. * * @return the original retry builder */ RetryBuilder done(); default ExponentialBackoffBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a Fibonacci backoff for retry. * * @see FibonacciBackoff @FibonacciBackoff */ interface FibonacciBackoffBuilder { /** * Sets the maximum delay between retries. Defaults to 1 minute. * * @param value the maximum delay, must be >= 0 * @param unit the maximum delay unit, must not be {@code null} * @return this fibonacci backoff builder * @see FibonacciBackoff#maxDelay() @FibonacciBackoff.maxDelay * @see FibonacciBackoff#maxDelayUnit() @FibonacciBackoff.maxDelayUnit */ FibonacciBackoffBuilder maxDelay(long value, ChronoUnit unit); /** * Returns the original retry builder. * * @return the original retry builder */ RetryBuilder done(); default FibonacciBackoffBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } /** * Configures a custom backoff for retry. * * @see CustomBackoff @CustomBackoff */ interface CustomBackoffBuilder { /** * Sets the custom backoff strategy in the form of a {@link Supplier} of {@link CustomBackoffStrategy} * instances. Mandatory. * * @see CustomBackoff#value() */ CustomBackoffBuilder strategy(Supplier value); /** * Returns the original retry builder. */ RetryBuilder done(); default CustomBackoffBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } } /** * Configures a timeout. * * @see Timeout @Timeout */ interface TimeoutBuilder { /** * Sets the timeout duration. Defaults to 1 second. * * @param value the timeout length, must be >= 0 * @param unit the timeout unit, must not be {@code null} * @return this timeout builder * @see Timeout#value() @Timeout.value * @see Timeout#unit() @Timeout.unit */ TimeoutBuilder duration(long value, ChronoUnit unit); /** * Sets a callback that will be invoked when an invocation times out. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the timeout callback, must not be {@code null} * @return this timeout builder */ TimeoutBuilder onTimeout(Runnable callback); /** * Sets a callback that will be invoked when an invocation finishes before the timeout. *

* The callback must be fast and non-blocking and must not throw an exception. * * @param callback the finished callback, must not be {@code null} * @return this timeout builder */ TimeoutBuilder onFinished(Runnable callback); /** * Returns the original fault tolerance builder. * * @return the original fault tolerance builder */ Builder done(); default TimeoutBuilder with(Consumer> consumer) { consumer.accept(this); return this; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy