")} is present on a business method,
- * then a bean of type {@link FaultTolerance} with qualifier
- * {@link io.smallrye.common.annotation.Identifier @Identifier("<identifier>")}
- * must exist. Such bean serves as a preconfigured set of fault tolerance strategies
- * and is used to guard invocations of the annotated business method(s).
- *
- * It is customary to create such bean by declaring a {@code static} producer field.
- * That removes all scoping concerns, because only one instance ever exists. Using
- * a non-static producer field or a producer method means that scoping must be carefully
- * considered, especially if stateful fault tolerance strategies are configured.
- *
- * The {@code @ApplyFaultTolerance} annotation may also be present on a bean class,
- * in which case it applies to all business methods declared by the class. If the
- * annotation is present both on the method and the class declaring the method,
- * the one on the method takes precedence.
- *
- * When {@code @ApplyFaultTolerance} applies to a business method, all other fault tolerance
- * annotations that would otherwise also apply to that method are ignored.
- *
- * A single preconfigured fault tolerance can be applied to multiple methods, as long as asynchrony
- * of all those methods is the same as the asynchrony of the fault tolerance instance. For example,
- * if the fault tolerance instance is created using {@code FaultTolerance.create()}, it can be
- * applied to all synchronous methods, but not to any asynchronous method. If the fault tolerance
- * instance is created using {@code FaultTolerance.createAsync()}, it can be applied to all
- * asynchronous methods that return {@code CompletionStage}, but not to synchronous methods or
- * asynchronous methods that return any other asynchronous type.
- *
- * A single preconfigured fault tolerance can even be applied to multiple methods with different
- * return types, as long as the constraint on method asynchrony described above is obeyed. In such
- * case, it is customary to declare the fault tolerance instance as {@code FaultTolerance}
- * for synchronous methods, {@code FaultTolerance>} for asynchronous
- * methods that return {@code CompletionStage}, and so on. Note that this effectively precludes
- * defining a useful fallback, because fallback can only be defined when the value type is known.
- *
- * Note that this annotation has the same differences to the standard MicroProfile Fault Tolerance
- * as {@link FaultTolerance}:
- *
- * asynchronous actions of type {@link java.util.concurrent.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.
- *
+ * @deprecated use {@link ApplyGuard}
*/
+@Deprecated(forRemoval = true)
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@@ -63,7 +23,8 @@
@Experimental("first attempt at providing reusable fault tolerance strategies")
public @interface ApplyFaultTolerance {
/**
- * The identifier of a preconfigured fault tolerance instance.
+ * @deprecated use {@link ApplyGuard#value()}
*/
+ @Deprecated(forRemoval = true)
String value();
}
diff --git a/api/src/main/java/io/smallrye/faulttolerance/api/ApplyGuard.java b/api/src/main/java/io/smallrye/faulttolerance/api/ApplyGuard.java
new file mode 100644
index 000000000..4a75cd3fb
--- /dev/null
+++ b/api/src/main/java/io/smallrye/faulttolerance/api/ApplyGuard.java
@@ -0,0 +1,61 @@
+package io.smallrye.faulttolerance.api;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import jakarta.interceptor.InterceptorBinding;
+
+import io.smallrye.common.annotation.Experimental;
+
+/**
+ * A special interceptor binding annotation to apply preconfigured fault tolerance.
+ * If {@code @ApplyGuard("")} is present on a business method,
+ * then a bean of type {@link Guard} or {@link TypedGuard} with qualifier
+ * {@link io.smallrye.common.annotation.Identifier @Identifier("<identifier>")}
+ * must exist. Such bean serves as a preconfigured set of fault tolerance strategies
+ * and is used to guard invocations of the annotated business method(s).
+ *
+ * It is customary to create such bean by declaring a {@code static} producer field.
+ * That removes all scoping concerns, because only one instance ever exists. Using
+ * a non-static producer field or a producer method means that scoping must be carefully
+ * considered, especially if stateful fault tolerance strategies are configured.
+ *
+ * The {@code @ApplyGuard} annotation may also be present on a bean class,
+ * in which case it applies to all business methods declared by the class. If the
+ * annotation is present both on the method and the class declaring the method,
+ * the one on the method takes precedence.
+ *
+ * When {@code @ApplyGuard} applies to a business method, all other fault tolerance
+ * annotations that would otherwise also apply to that method are ignored.
+ *
+ * A single preconfigured fault tolerance can be applied to multiple methods.
+ * If the preconfigured fault tolerance is of type {@code TypedGuard}, then all methods
+ * must have the same return type. If the preconfigured fault tolerance is of type {@code Guard},
+ * no such requirement applies; note that in this case, there is no way to define a fallback.
+ *
+ * Note that this annotation has the same differences to standard MicroProfile Fault Tolerance
+ * as {@code Guard} / {@code TypedGuard}:
+ *
+ * asynchronous actions of type {@link java.util.concurrent.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.
+ *
+ * If multiple beans of type {@code Guard} or {@code TypedGuard} with the same identifier
+ * exist, a deployment problem occurs.
+ */
+@Inherited
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@InterceptorBinding
+@Experimental("second attempt at providing reusable fault tolerance strategies")
+public @interface ApplyGuard {
+ /**
+ * The identifier of a preconfigured {@link Guard} or {@link TypedGuard} instance.
+ */
+ String value();
+}
diff --git a/api/src/main/java/io/smallrye/faulttolerance/api/CircuitBreakerMaintenance.java b/api/src/main/java/io/smallrye/faulttolerance/api/CircuitBreakerMaintenance.java
index 201e62988..bc9b35008 100644
--- a/api/src/main/java/io/smallrye/faulttolerance/api/CircuitBreakerMaintenance.java
+++ b/api/src/main/java/io/smallrye/faulttolerance/api/CircuitBreakerMaintenance.java
@@ -20,19 +20,27 @@
import io.smallrye.common.annotation.Experimental;
/**
- * Allows reading and observing current state of circuit breakers and reseting them to the initial (closed) state.
+ * Allows reading and observing current state of circuit breakers and resetting them to the initial (closed) state.
* To access a specific circuit breaker, it must be given a name using {@link CircuitBreakerName @CircuitBreakerName}
- * or {@link FaultTolerance.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
+ * or {@link Guard.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
*/
@Experimental("first attempt at providing maintenance access to circuit breakers")
public interface CircuitBreakerMaintenance {
+ /**
+ * Returns a {@link CircuitBreakerMaintenance} instance that provides maintenance access to existing
+ * circuit breakers.
+ */
+ static CircuitBreakerMaintenance get() {
+ return SpiAccess.get().circuitBreakerMaintenance();
+ }
+
/**
* Returns current state of the circuit breaker with given {@code name}.
* Note that there's no guarantee that the circuit breaker will stay in that state for any time,
* so this method is only useful for monitoring.
*
* It is an error to use a {@code name} that wasn't registered using {@link CircuitBreakerName @CircuitBreakerName}
- * or {@link FaultTolerance.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
+ * or {@link Guard.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
*/
CircuitBreakerState currentState(String name);
@@ -41,7 +49,7 @@ public interface CircuitBreakerMaintenance {
* changes state.
*
* It is an error to use a {@code name} that wasn't registered using {@link CircuitBreakerName @CircuitBreakerName}
- * or {@link FaultTolerance.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
+ * or {@link Guard.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
*
* The callback must be fast and non-blocking and must not throw an exception.
*/
@@ -54,7 +62,7 @@ public interface CircuitBreakerMaintenance {
* and perhaps emergency maintenance tasks.
*
* It is an error to use a {@code name} that wasn't registered using {@link CircuitBreakerName @CircuitBreakerName}
- * or {@link FaultTolerance.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
+ * or {@link Guard.Builder.CircuitBreakerBuilder#name(String) withCircuitBreaker().name("...")}.
*/
void reset(String name);
diff --git a/api/src/main/java/io/smallrye/faulttolerance/api/FaultTolerance.java b/api/src/main/java/io/smallrye/faulttolerance/api/FaultTolerance.java
index 597be6d73..21ffec318 100644
--- a/api/src/main/java/io/smallrye/faulttolerance/api/FaultTolerance.java
+++ b/api/src/main/java/io/smallrye/faulttolerance/api/FaultTolerance.java
@@ -12,153 +12,108 @@
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 jakarta.enterprise.util.TypeLiteral;
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 java.util.concurrent.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
+ * @deprecated use {@link Guard} or {@link TypedGuard}
*/
+@Deprecated(forRemoval = true)
@Experimental("first attempt at providing programmatic API")
public interface FaultTolerance {
/**
- * Returns a {@link CircuitBreakerMaintenance} instance that provides maintenance access to existing
- * circuit breakers.
+ * @deprecated use {@link CircuitBreakerMaintenance#get()}
*/
+ @Deprecated(forRemoval = true)
static CircuitBreakerMaintenance circuitBreakerMaintenance() {
- return FaultToleranceSpiAccess.get().circuitBreakerMaintenance();
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard} and {@code adaptCallable}
*/
+ @Deprecated(forRemoval = true)
static Builder> createCallable(Callable action) {
- return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptCallable(action));
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard} and {@code adaptSupplier}
*/
+ @Deprecated(forRemoval = true)
static Builder> createSupplier(Supplier action) {
- return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptSupplier(action));
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard}; there's no direct support
+ * for guarding {@code Runnable}s, but adapting to {@code Supplier} by using
+ * {@code adaptSupplier} should be close enough
*/
+ @Deprecated(forRemoval = true)
static Builder createRunnable(Runnable action) {
- return FaultToleranceSpiAccess.get().newBuilder(ft -> ft.adaptRunnable(action));
+ return SpiAccess.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()}.
+ * @deprecated use {@link Guard#create()} or {@link TypedGuard#create(Class)}
+ * or {@link TypedGuard#create(TypeLiteral)}
*/
+ @Deprecated(forRemoval = true)
static Builder> create() {
- return FaultToleranceSpiAccess.get().newBuilder(Function.identity());
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard} and {@code adaptCallable}
*/
+ @Deprecated(forRemoval = true)
static Builder, Callable>> createAsyncCallable(
Callable> action) {
- return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptCallable(action));
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard} and {@code adaptSupplier}
*/
+ @Deprecated(forRemoval = true)
static Builder, Supplier>> createAsyncSupplier(
Supplier> action) {
- return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptSupplier(action));
+ return SpiAccess.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.
+ * @deprecated use {@link Guard} or {@link TypedGuard}; there's no direct support
+ * for guarding {@code Runnable}s, but adapting to {@code Supplier} by using
+ * {@code adaptSupplier} should be close enough
*/
+ @Deprecated(forRemoval = true)
static Builder, Runnable> createAsyncRunnable(Runnable action) {
- return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, ft -> ft.adaptRunnable(action));
+ return SpiAccess.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()}.
+ * @deprecated use {@link Guard#create()} or {@link TypedGuard#create(Class)}
+ * or {@link TypedGuard#create(TypeLiteral)}
*/
+ @Deprecated(forRemoval = true)
static Builder, FaultTolerance>> createAsync() {
- return FaultToleranceSpiAccess.get().newAsyncBuilder(CompletionStage.class, Function.identity());
+ return SpiAccess.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.
+ * @deprecated use {@link Guard#call(Callable, Class)} or {@link Guard#call(Callable, TypeLiteral)}
+ * or {@link TypedGuard#call(Callable)}
*/
+ @Deprecated(forRemoval = true)
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.
+ * @deprecated use {@link Guard#get(Supplier, Class)} or {@link Guard#get(Supplier, TypeLiteral)}
+ * or {@link TypedGuard#get(Supplier)}
*/
+ @Deprecated(forRemoval = true)
default T get(Supplier action) {
try {
return call(action::get);
@@ -170,12 +125,10 @@ default T get(Supplier action) {
}
/**
- * 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.
+ * @deprecated use {@link Guard#get(Supplier, Class)} or {@link Guard#get(Supplier, TypeLiteral)}
+ * or {@link TypedGuard#get(Supplier)}
*/
+ @Deprecated(forRemoval = true)
default void run(Runnable action) {
try {
call(() -> {
@@ -190,909 +143,359 @@ default void run(Runnable 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 () -> call(action)}.
- *
- * @see #call(Callable)
+ * @deprecated use {@link Guard#adaptCallable(Callable, Class)} or {@link Guard#adaptCallable(Callable, TypeLiteral)}
+ * or {@link TypedGuard#adaptCallable(Callable)}
*/
+ @Deprecated(forRemoval = true)
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)
+ * @deprecated use {@link Guard#adaptSupplier(Supplier, Class)} or {@link Guard#adaptSupplier(Supplier, TypeLiteral)}
+ * or {@link TypedGuard#adaptSupplier(Supplier)}
*/
+ @Deprecated(forRemoval = true)
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)
+ * @deprecated use {@link Guard#adaptSupplier(Supplier, Class)} or {@link Guard#adaptSupplier(Supplier, TypeLiteral)}
+ * or {@link TypedGuard#adaptSupplier(Supplier)}
*/
+ @Deprecated(forRemoval = true)
default Runnable adaptRunnable(Runnable action) {
return () -> run(action);
}
/**
- * Casts this {@link FaultTolerance} object so that it guards actions of a different type.
- * Since the type of the action is only used in fallback, this is usually safe; if this
- * {@code FaultTolerance} object contains a fallback, this method throws an exception.
- *
- * Note that this method may only be used to cast synchronous {@code FaultTolerance}.
- * If this {@code FaultTolerance} object guards asynchronous actions, this method throws
- * an exception.
- *
- * @param type of value of the guarded action
+ * @deprecated use {@link Guard} or {@link TypedGuard}, which unifies synchronous and asynchronous invocations
*/
+ @Deprecated(forRemoval = true)
FaultTolerance cast();
/**
- * Casts this {@link FaultTolerance} object so that it guards actions of a different type.
- * Since the type of the action is only used in fallback, this is usually safe; if this
- * {@code FaultTolerance} object contains a fallback, this method throws an exception.
- *
- * Note that this method may only be used to cast asynchronous {@code FaultTolerance}
- * of given type (such as {@code CompletionStage} or {@code Uni}). If this {@code FaultTolerance}
- * object guards synchronous actions or asynchronous actions of different type, this method
- * throws an exception.
- *
- * @param asyncType the asynchronous type, such as {@code CompletionStage} or {@code Uni}
- * @param type of value of the guarded action
+ * @deprecated use {@link Guard} or {@link TypedGuard}, which unifies synchronous and asynchronous invocations
*/
+ @Deprecated(forRemoval = true)
FaultTolerance castAsync(Class> asyncType);
/**
- * 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
+ * @deprecated use {@link Guard.Builder} or {@link TypedGuard.Builder}
*/
+ @Deprecated(forRemoval = true)
interface Builder {
- /**
- * Assigns a description to the resulting set of configured fault tolerance strategies. The description
- * is used in logging messages and exception messages, and also as an identifier for metrics.
- *
- * 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
BulkheadBuilder withBulkhead();
- /**
- * Adds a circuit breaker strategy.
- *
- * @return a builder to configure the circuit breaker strategy
- * @see CircuitBreaker @CircuitBreaker
- */
+ @Deprecated(forRemoval = true)
CircuitBreakerBuilder withCircuitBreaker();
- /**
- * Adds a fallback strategy.
- *
- * @return a builder to configure the fallback strategy
- * @see Fallback @Fallback
- */
+ @Deprecated(forRemoval = true)
FallbackBuilder withFallback();
- /**
- * Adds a rate limit strategy.
- *
- * @return a builder to configure the rate limit strategy
- * @see RateLimit @RateLimit
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
RetryBuilder withRetry();
- /**
- * Adds a timeout strategy.
- *
- * @return a builder to configure the timeout strategy
- * @see Timeout @Timeout
- */
+ @Deprecated(forRemoval = true)
TimeoutBuilder withTimeout();
- /**
- * Configures whether the guarded action should be offloaded to another thread. Thread offload is
- * only possible for asynchronous actions. If this builder was not created using {@code createAsync},
- * attempting to enable thread offload 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
- */
+ @Deprecated(forRemoval = true)
Builder withThreadOffload(boolean value);
- /**
- * Configures the executor to use when offloading the guarded action to another thread. Thread
- * offload is only possible for asynchronous actions. If this builder was not created using
- * {@code createAsync}, this method throws an exception.
- *
- * If this method is not called, the guarded action is offloaded to the default executor
- * provided by the integrator.
- *
- * @param executor the executor to which the guarded action should be offloaded
- * @return this fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder withThreadOffloadExecutor(Executor executor);
- /**
- * Returns a ready-to-use instance of {@code FaultTolerance} or guarded {@code Callable}, depending on
- * how this builder was created.
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default Builder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
- /**
- * Configures a bulkhead.
- *
- * @see Bulkhead @Bulkhead
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
BulkheadBuilder queueSize(int value);
/**
- * Enables bulkhead queueing for synchronous actions executed on virtual threads.
- * This makes it possible to call {@link #queueSize(int)} even if this builder does
- * not configure fault tolerance for asynchronous actions.
- *
- * If you use this method, you have to ensure that the guard
- * is executed on a virtual thread.
- *
- * @return this bulkhead builder
+ * @deprecated use {@code enableSynchronousQueueing()}
*/
+ @Deprecated(forRemoval = true)
BulkheadBuilder enableVirtualThreadsQueueing();
- /**
- * 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
BulkheadBuilder onFinished(Runnable callback);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default BulkheadBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a circuit breaker.
- *
- * @see CircuitBreaker @CircuitBreaker
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default CircuitBreakerBuilder failOn(Class extends Throwable> 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default CircuitBreakerBuilder skipOn(Class extends Throwable> 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
CircuitBreakerBuilder onPrevented(Runnable callback);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default CircuitBreakerBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a fallback.
- *
- * @see Fallback @Fallback
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default FallbackBuilder applyOn(Class extends Throwable> 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default FallbackBuilder skipOn(Class extends Throwable> 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
- */
+ @Deprecated(forRemoval = true)
FallbackBuilder when(Predicate value);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default FallbackBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a rate limit.
- *
- * @see RateLimit @RateLimit
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
RateLimitBuilder onRejected(Runnable callback);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default RateLimitBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a retry.
- *
- * @see Retry @Retry
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default RetryBuilder retryOn(Class extends Throwable> 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
default RetryBuilder abortOn(Class extends Throwable> value) {
return abortOn(Collections.singleton(Objects.requireNonNull(value)));
}
- /**
- * Sets a predicate to determine when a result should be considered failure and retry
- * should be attempted. All results that do not match this predicate are implicitly
- * considered success.
- *
- * @param value the predicate, must not be {@code null}
- * @return this retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder whenResult(Predicate value);
- /**
- * @deprecated use {@link #whenException(Predicate)}
- */
@Deprecated(forRemoval = true)
default RetryBuilder when(Predicate value) {
return whenException(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 retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder whenException(Predicate value);
- /**
- * Sets a before retry handler, which is called before each retry, but not before the original attempt.
- *
- * @param value the before retry handler, must not be {@code null}
- * @return this retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder beforeRetry(Runnable value);
- /**
- * Sets a before retry handler, which is called before each retry, but not before the original attempt.
- *
- * @param value the before retry handler, must not be {@code null}
- * @return this retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder beforeRetry(Consumer 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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
RetryBuilder onFailure(Runnable callback);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default RetryBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
- /**
- * Configures an exponential backoff for retry.
- *
- * @see ExponentialBackoff @ExponentialBackoff
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
ExponentialBackoffBuilder maxDelay(long value, ChronoUnit unit);
- /**
- * Returns the original retry builder.
- *
- * @return the original retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder done();
+ @Deprecated(forRemoval = true)
default ExponentialBackoffBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a Fibonacci backoff for retry.
- *
- * @see FibonacciBackoff @FibonacciBackoff
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
FibonacciBackoffBuilder maxDelay(long value, ChronoUnit unit);
- /**
- * Returns the original retry builder.
- *
- * @return the original retry builder
- */
+ @Deprecated(forRemoval = true)
RetryBuilder done();
+ @Deprecated(forRemoval = true)
default FibonacciBackoffBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
}
}
- /**
- * Configures a custom backoff for retry.
- *
- * @see CustomBackoff @CustomBackoff
- */
+ @Deprecated(forRemoval = true)
interface CustomBackoffBuilder {
- /**
- * Sets the custom backoff strategy in the form of a {@link Supplier} of {@link CustomBackoffStrategy}
- * instances. Mandatory.
- *
- * @see CustomBackoff#value()
- */
+ @Deprecated(forRemoval = true)
CustomBackoffBuilder strategy(Supplier value);
- /**
- * Returns the original retry builder.
- */
+ @Deprecated(forRemoval = true)
RetryBuilder done();
+ @Deprecated(forRemoval = true)
default CustomBackoffBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
@@ -1100,50 +503,21 @@ default CustomBackoffBuilder with(Consumer> con
}
}
- /**
- * Configures a timeout.
- *
- * @see Timeout @Timeout
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
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
- */
+ @Deprecated(forRemoval = true)
TimeoutBuilder onFinished(Runnable callback);
- /**
- * Returns the original fault tolerance builder.
- *
- * @return the original fault tolerance builder
- */
+ @Deprecated(forRemoval = true)
Builder done();
+ @Deprecated(forRemoval = true)
default TimeoutBuilder with(Consumer> consumer) {
consumer.accept(this);
return this;
diff --git a/api/src/main/java/io/smallrye/faulttolerance/api/Guard.java b/api/src/main/java/io/smallrye/faulttolerance/api/Guard.java
new file mode 100644
index 000000000..e42d9d11b
--- /dev/null
+++ b/api/src/main/java/io/smallrye/faulttolerance/api/Guard.java
@@ -0,0 +1,946 @@
+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.Executor;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+import jakarta.enterprise.util.TypeLiteral;
+
+import org.eclipse.microprofile.faulttolerance.Asynchronous;
+import org.eclipse.microprofile.faulttolerance.Bulkhead;
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+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, rate limit, retry.
+ * and timeout. Synchronous as well as asynchronous actions may be guarded, asynchronous actions may optionally
+ * be offloaded to another thread. This interface doesn't support fallback; for that, use {@link TypedGuard}.
+ *
+ * An instance of this interface represents a configured set of fault tolerance strategies. It can be used to
+ * guard a {@link #call(Callable, Class) Callable} or {@link #get(Supplier, Class) Supplier} invocation, or adapt
+ * an unguarded {@link #adaptCallable(Callable, Class) Callable} or {@link #adaptSupplier(Supplier, Class) Supplier}
+ * to a guarded one.
+ *
+ * The {@link #create()} method return a builder that allows configuring the supported fault tolerance strategies.
+ * Order of builder method invocations does not matter, the fault tolerance strategies are always applied
+ * in a predefined order: retry > circuit breaker > rate limit > timeout > bulkhead > thread offload
+ * > guarded action.
+ *
+ * Note that bulkheads, circuit breakers and rate limits are stateful, so there's a big difference between guarding
+ * multiple actions using the same {@code Guard} object and using a separate {@code Guard} object for each action.
+ * Using a single {@code Guard} 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 java.util.concurrent.Future} are not supported;
+ * the circuit breaker and retry strategies always inspect the cause chain of exceptions,
+ * following the behavior of SmallRye Fault Tolerance in the non-compatible mode.
+ *
+ */
+@Experimental("second attempt at providing programmatic API")
+public interface Guard {
+ /**
+ * Creates a builder for producing a {@link Guard} object representing a set of configured fault tolerance
+ * strategies. It can be used to execute actions using {@link #call(Callable, Class) call()} or
+ * {@link #get(Supplier, Class) get()}.
+ */
+ static Builder create() {
+ return SpiAccess.get().newGuardBuilder();
+ }
+
+ /**
+ * Calls given {@code action}, which returns given {@code type}, and guards the call by this configured set
+ * of fault tolerance strategies.
+ *
+ * The given {@code type} is used to determine if the {@code action} is synchronous or asynchronous.
+ * If the {@code action} is synchronous, it is always executed on the same thread that calls this method.
+ * If the {@code action} is asynchronous, it may be offloaded to another thread depending on how the builder
+ * was configured.
+ */
+ T call(Callable action, Class type) throws Exception;
+
+ /**
+ * Calls given {@code action}, which returns given {@code type}, and guards the call by this configured set
+ * of fault tolerance strategies.
+ *
+ * The given {@code type} is used to determine if the {@code action} is synchronous or asynchronous.
+ * If the {@code action} is synchronous, it is always executed on the same thread that calls this method.
+ * If the {@code action} is asynchronous, it may be offloaded to another thread depending on how the builder
+ * was configured.
+ */
+ T call(Callable action, TypeLiteral type) throws Exception;
+
+ /**
+ * Calls given {@code action}, which returns given {@code type}, and guards the call by this configured set
+ * of fault tolerance strategies.
+ *
+ * The given {@code type} is used to determine if the {@code action} is synchronous or asynchronous.
+ * If the {@code action} is synchronous, it is always executed on the same thread that calls this method.
+ * If the {@code action} is asynchronous, it may be offloaded to another thread depending on how the builder
+ * was configured.
+ */
+ T get(Supplier action, Class type);
+
+ /**
+ * Calls given {@code action}, which returns given {@code type}, and guards the call by this configured set
+ * of fault tolerance strategies.
+ *
+ * The given {@code type} is used to determine if the {@code action} is synchronous or asynchronous.
+ * If the {@code action} is synchronous, it is always executed on the same thread that calls this method.
+ * If the {@code action} is asynchronous, it may be offloaded to another thread depending on how the builder
+ * was configured.
+ */
+ T get(Supplier action, TypeLiteral type);
+
+ /**
+ * 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, type)}.
+ *
+ * @see #call(Callable, Class)
+ */
+ default Callable adaptCallable(Callable action, Class type) {
+ return () -> call(action, type);
+ }
+
+ /**
+ * 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, type)}.
+ *
+ * @see #call(Callable, TypeLiteral)
+ */
+ default Callable adaptCallable(Callable action, TypeLiteral type) {
+ return () -> call(action, type);
+ }
+
+ /**
+ * 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, type)}.
+ *
+ * @see #get(Supplier, Class)
+ */
+ default Supplier adaptSupplier(Supplier action, Class type) {
+ return () -> get(action, type);
+ }
+
+ /**
+ * 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, type)}.
+ *
+ * @see #get(Supplier, TypeLiteral)
+ */
+ default Supplier adaptSupplier(Supplier action, TypeLiteral type) {
+ return () -> get(action, type);
+ }
+
+ /**
+ * 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.
+ */
+ interface Builder {
+ /**
+ * Assigns a description to the resulting set of configured fault tolerance strategies. The description
+ * is used in logging messages and exception messages, and also as an identifier for metrics.
+ *
+ * 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 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 an asynchronous guarded action should be offloaded to another thread.
+ *
+ * @param value whether an asynchronous guarded action should be offloaded to another thread
+ * @return this fault tolerance builder
+ * @see Asynchronous @Asynchronous
+ * @see AsynchronousNonBlocking @AsynchronousNonBlocking
+ */
+ Builder withThreadOffload(boolean value);
+
+ /**
+ * Configures the executor to use when offloading the guarded action to another thread.
+ *
+ * If this method is not called but thread offload is enabled using {@link #withThreadOffload(boolean)},
+ * an asynchronous guarded action is offloaded to the default executor provided by the integrator.
+ *
+ * @param executor the executor to which the guarded action should be offloaded
+ * @return this fault tolerance builder
+ */
+ Builder withThreadOffloadExecutor(Executor executor);
+
+ /**
+ * Returns a ready-to-use instance of {@code Guard}.
+ */
+ Guard build();
+
+ /**
+ * Syntactic sugar for calling the builder methods conditionally without breaking the invocation chain.
+ * For example:
+ *
+ *
+ *
{@code
+ * Guard.create()
+ * .withRetry() ... .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
+ * @see Bulkhead#value() @Bulkhead.value
+ */
+ BulkheadBuilder limit(int value);
+
+ /**
+ * Sets the maximum size of the bulkhead queue. Defaults to 10.
+ *
+ * @param value the queue size, must be >= 1
+ * @return this bulkhead builder
+ * @see Bulkhead#waitingTaskQueue() @Bulkhead.waitingTaskQueue
+ */
+ BulkheadBuilder queueSize(int value);
+
+ /**
+ * Enables bulkhead queueing for synchronous actions.
+ *
+ * If you use this method, you have to ensure that the guard
+ * is executed on a virtual thread.
+ *
+ * @return this bulkhead builder
+ */
+ BulkheadBuilder enableSynchronousQueueing();
+
+ /**
+ * 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 extends Throwable> 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 extends Throwable> 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 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
+ * @see RateLimit#value() @RateLimit.value
+ */
+ 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
+ * @see RateLimit#window() @RateLimit.window
+ * @see RateLimit#windowUnit() @RateLimit.windowUnit
+ */
+ 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
+ * @see RateLimit#minSpacing() @RateLimit.minSpacing
+ * @see RateLimit#minSpacingUnit() @RateLimit.minSpacingUnit
+ */
+ 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
+ * @see RateLimit#type() @RateLimit.type
+ */
+ 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 extends Throwable> 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 extends Throwable> value) {
+ return abortOn(Collections.singleton(Objects.requireNonNull(value)));
+ }
+
+ /**
+ * Sets a predicate to determine when a result should be considered failure and retry
+ * should be attempted. All results that do not match this predicate are implicitly
+ * considered success.
+ *
+ * @param value the predicate, must not be {@code null}
+ * @return this retry builder
+ */
+ RetryBuilder whenResult(Predicate 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 retry builder
+ * @see BeforeRetry @BeforeRetry
+ */
+ RetryBuilder whenException(Predicate value);
+
+ /**
+ * Sets a before retry handler, which is called before each retry, but not before the original attempt.
+ *
+ * @param value the before retry handler, must not be {@code null}
+ * @return this retry builder
+ * @see BeforeRetry @BeforeRetry
+ */
+ RetryBuilder beforeRetry(Runnable value);
+
+ /**
+ * Sets a before retry handler, which is called before each retry, but not before the original attempt.
+ *
+ * @param value the before retry handler, must not be {@code null}
+ * @return this retry builder
+ */
+ RetryBuilder beforeRetry(Consumer 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