Skip to content

Commit 86fffa9

Browse files
committed
Add checked predicates, clarify the meaning of failure vs exception
This commit adds checked predicates and bi-predicates to config builders. This extra lenience will make it easier to build policies, and always should have been supported since exceptions from predicates are ignored anyways. This commit also clarifies the meaning of "failure" vs "exception". Unfortunately, "failure" has been very overloaded in Failsafe to mean an exception or something that a policy actually considers a failure, which may or may not be a particular exception. This commit deprecates many of the fields that record or get "failures" where failure is really meant to mean an exception, and adds new methods with "exception" naming.
1 parent 94d85aa commit 86fffa9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+526
-386
lines changed

src/main/java/dev/failsafe/AsyncExecution.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ public interface AsyncExecution<R> extends ExecutionContext<R> {
3838
boolean isComplete();
3939

4040
/**
41-
* Records an execution {@code result} or {@code failure} which triggers failure handling, if needed, by the
41+
* Records an execution {@code result} or {@code exception} which triggers failure handling, if needed, by the
4242
* configured policies. If policy handling is not possible or already complete, the resulting {@link
4343
* CompletableFuture} is completed.
4444
*
4545
* @throws IllegalStateException if the most recent execution was already recorded or the execution is complete
4646
*/
47-
void record(R result, Throwable failure);
47+
void record(R result, Throwable exception);
4848

4949
/**
5050
* Records an execution {@code result} which triggers failure handling, if needed, by the configured policies. If
@@ -55,10 +55,16 @@ public interface AsyncExecution<R> extends ExecutionContext<R> {
5555
void recordResult(R result);
5656

5757
/**
58-
* Records an execution {@code failure} which triggers failure handling, if needed, by the configured policies. If
59-
* policy handling is not possible or already complete, the resulting {@link CompletableFuture} is completed.
58+
* Records an {@code exception} which triggers failure handling, if needed, by the configured policies. If policy
59+
* handling is not possible or already complete, the resulting {@link CompletableFuture} is completed.
6060
*
6161
* @throws IllegalStateException if the most recent execution was already recorded or the execution is complete
6262
*/
63+
void recordException(Throwable exception);
64+
65+
/**
66+
* @deprecated Use {@link #recordException(Throwable)} instead
67+
*/
68+
@Deprecated
6369
void recordFailure(Throwable failure);
6470
}

src/main/java/dev/failsafe/AsyncExecutionImpl.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,15 @@ public boolean isComplete() {
8585
}
8686

8787
@Override
88-
public void record(R result, Throwable failure) {
88+
public void record(R result, Throwable exception) {
8989
Assert.state(!recorded, "The most recent execution has already been recorded or completed");
9090
recorded = true;
9191

9292
// Guard against race with a timeout expiring
9393
synchronized (future) {
9494
if (!attemptRecorded) {
9595
Assert.state(!completed, "Execution has already been completed");
96-
record(new ExecutionResult<>(result, failure));
96+
record(new ExecutionResult<>(result, exception));
9797
}
9898

9999
// Proceed with handling the recorded result
@@ -107,8 +107,14 @@ public void recordResult(R result) {
107107
}
108108

109109
@Override
110+
public void recordException(Throwable exception) {
111+
record(null, exception);
112+
}
113+
114+
@Override
115+
@Deprecated
110116
public void recordFailure(Throwable failure) {
111-
record(null, failure);
117+
recordException(failure);
112118
}
113119

114120
@Override
@@ -154,7 +160,7 @@ private void complete(ExecutionResult<R> result, Throwable error) {
154160
else {
155161
if (error instanceof CompletionException)
156162
error = error.getCause();
157-
future.completeResult(ExecutionResult.failure(error));
163+
future.completeResult(ExecutionResult.exception(error));
158164
}
159165
}
160166
}

src/main/java/dev/failsafe/BulkheadBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public Bulkhead<R> build() {
5050
/**
5151
* Configures the {@code maxWaitTime} to wait for permits to be available. If permits cannot be acquired before the
5252
* {@code maxWaitTime} is exceeded, then the bulkhead will throw {@link BulkheadFullException}.
53+
* <p>
54+
* This setting only applies when the resulting Bulkhead is used with the {@link Failsafe} class. It does not apply
55+
* when the Bulkhead is used in a standalone way.
56+
* </p>
5357
*
5458
* @throws NullPointerException if {@code maxWaitTime} is null
5559
*/

src/main/java/dev/failsafe/BulkheadConfig.java

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public int getMaxConcurrency() {
5050
/**
5151
* Returns the max time to wait for permits to be available. If permits cannot be acquired before the max wait time is
5252
* exceeded, then the bulkhead will throw {@link BulkheadFullException}.
53+
* <p>
54+
* This setting only applies when the Bulkhead is used with the {@link Failsafe} class. It does not apply when the
55+
* Bulkhead is used in a standalone way.
56+
* </p>
5357
*
5458
* @see BulkheadBuilder#withMaxWaitTime(Duration)
5559
*/

src/main/java/dev/failsafe/CircuitBreaker.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ enum State {
112112
* to the configured success or failure thresholding capacity.
113113
* @see #tryAcquirePermit()
114114
* @see #recordResult(Object)
115-
* @see #recordFailure(Throwable)
115+
* @see #recordException(Throwable)
116116
* @see #recordSuccess()
117117
* @see #recordFailure()
118118
*/
@@ -126,7 +126,7 @@ default void acquirePermit() {
126126
* automatically released when a result or failure is recorded.
127127
*
128128
* @see #recordResult(Object)
129-
* @see #recordFailure(Throwable)
129+
* @see #recordException(Throwable)
130130
* @see #recordSuccess()
131131
* @see #recordFailure()
132132
*/
@@ -229,8 +229,14 @@ default void acquirePermit() {
229229
void recordFailure();
230230

231231
/**
232-
* Records an execution {@code failure} as a success or failure based on the failure configuration.
232+
* Records an {@code exception} as a success or failure based on the exception configuration.
233233
*/
234+
void recordException(Throwable exception);
235+
236+
/**
237+
* @deprecated Use {@link #recordException(Throwable)} instead.
238+
*/
239+
@Deprecated
234240
void recordFailure(Throwable failure);
235241

236242
/**

src/main/java/dev/failsafe/CircuitBreakerBuilder.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@
1717

1818
import dev.failsafe.event.CircuitBreakerStateChangedEvent;
1919
import dev.failsafe.event.EventListener;
20+
import dev.failsafe.function.CheckedBiPredicate;
21+
import dev.failsafe.function.CheckedPredicate;
2022
import dev.failsafe.internal.CircuitBreakerImpl;
2123
import dev.failsafe.internal.util.Assert;
2224
import dev.failsafe.internal.util.Durations;
2325

2426
import java.time.Duration;
25-
import java.util.function.BiPredicate;
26-
import java.util.function.Predicate;
2727

2828
/**
2929
* Builds {@link CircuitBreaker} instances.
3030
* <ul>
3131
* <li>By default, any exception is considered a failure and will be handled by the policy. You can override this by
3232
* specifying your own {@code handle} conditions. The default exception handling condition will only be overridden by
33-
* another condition that handles failure exceptions such as {@link #handle(Class)} or {@link #handleIf(BiPredicate)}.
33+
* another condition that handles exceptions such as {@link #handle(Class)} or {@link #handleIf(CheckedBiPredicate)}.
3434
* Specifying a condition that only handles results, such as {@link #handleResult(Object)} or
35-
* {@link #handleResultIf(Predicate)} will not replace the default exception handling condition.</li>
36-
* <li>If multiple {@code handle} conditions are specified, any condition that matches an execution result or failure
35+
* {@link #handleResultIf(CheckedPredicate)} will not replace the default exception handling condition.</li>
36+
* <li>If multiple {@code handle} conditions are specified, any condition that matches an execution result or exception
3737
* will trigger policy handling.</li>
3838
* </ul>
3939
* <p>

src/main/java/dev/failsafe/DelayablePolicyBuilder.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public S withDelay(Duration delay) {
6363
* <li>Any configured jitter is still applied to DelayFunction provided values
6464
* <li>Any configured max duration is still applied to DelayFunction provided values
6565
* <li>The {@link ExecutionContext} that is provided to the {@code delayFunction} may be {@code null} if the prior execution
66-
* failure was manually recorded outside of a Failsafe execution.</li>
66+
* exception was manually recorded outside of a Failsafe execution.</li>
6767
* </ul>
6868
* </p>
6969
*
@@ -78,7 +78,7 @@ public S withDelayFn(ContextualSupplier<R, Duration> delayFunction) {
7878

7979
/**
8080
* Sets the {@code delayFunction} that computes the next delay before allowing another execution. Delays will only
81-
* occur for failures that are assignable from the {@code failure}.
81+
* occur for exceptions that are assignable from the {@code exception}.
8282
* <p>
8383
* The {@code delayFunction} must complete quickly, not have side-effects, and always return the same result for the
8484
* same input. Exceptions thrown by the {@code delayFunction} method will <strong>not</strong> be handled and will
@@ -91,20 +91,20 @@ public S withDelayFn(ContextualSupplier<R, Duration> delayFunction) {
9191
* <li>Any configured jitter is still applied to DelayFunction provided values
9292
* <li>Any configured max duration is still applied to DelayFunction provided values
9393
* <li>The {@link ExecutionContext} that is provided to the {@code delayFunction} may be {@code null} if the prior execution
94-
* failure was manually recorded outside of a Failsafe execution.</li>
94+
* exception was manually recorded outside of a Failsafe execution.</li>
9595
* </ul>
9696
* </p>
9797
*
9898
* @param delayFunction the function to use to compute the delay before a next attempt
99-
* @param failure the execution failure that is expected in order to trigger the delay
100-
* @param <F> failure type
101-
* @throws NullPointerException if {@code delayFunction} or {@code failure} are null
99+
* @param exception the execution exception that is expected in order to trigger the delay
100+
* @param <F> exception type
101+
* @throws NullPointerException if {@code delayFunction} or {@code exception} are null
102102
*/
103103
@SuppressWarnings("unchecked")
104-
public <F extends Throwable> S withDelayFnOn(ContextualSupplier<R, Duration> delayFunction, Class<F> failure) {
104+
public <F extends Throwable> S withDelayFnOn(ContextualSupplier<R, Duration> delayFunction, Class<F> exception) {
105105
withDelayFn(delayFunction);
106-
Assert.notNull(failure, "failure");
107-
config.delayFailure = failure;
106+
Assert.notNull(exception, "exception");
107+
config.delayException = exception;
108108
return (S) this;
109109
}
110110

@@ -123,7 +123,7 @@ public <F extends Throwable> S withDelayFnOn(ContextualSupplier<R, Duration> del
123123
* <li>Any configured jitter is still applied to DelayFunction provided values
124124
* <li>Any configured max duration is still applied to DelayFunction provided values
125125
* <li>The {@link ExecutionContext} that is provided to the {@code delayFunction} may be {@code null} if the prior execution
126-
* failure was manually recorded outside of a Failsafe execution.</li>
126+
* exception was manually recorded outside of a Failsafe execution.</li>
127127
* </ul>
128128
* </p>
129129
*

src/main/java/dev/failsafe/DelayablePolicyConfig.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
public abstract class DelayablePolicyConfig<R> extends FailurePolicyConfig<R> {
2929
Duration delay;
3030
R delayResult;
31-
Class<? extends Throwable> delayFailure;
31+
Class<? extends Throwable> delayException;
3232
ContextualSupplier<R, Duration> delayFn;
3333

3434
protected DelayablePolicyConfig() {
@@ -38,7 +38,7 @@ protected DelayablePolicyConfig(DelayablePolicyConfig<R> config) {
3838
super(config);
3939
delay = config.delay;
4040
delayResult = config.delayResult;
41-
delayFailure = config.delayFailure;
41+
delayException = config.delayException;
4242
delayFn = config.delayFn;
4343
}
4444

@@ -67,8 +67,8 @@ public ContextualSupplier<R, Duration> getDelayFn() {
6767
*
6868
* @see DelayablePolicyBuilder#withDelayFnOn(ContextualSupplier, Class)
6969
*/
70-
public Class<? extends Throwable> getDelayFailure() {
71-
return delayFailure;
70+
public Class<? extends Throwable> getDelayException() {
71+
return delayException;
7272
}
7373

7474
/**

src/main/java/dev/failsafe/Execution.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ static <R> Execution<R> of(Policy<R> outerPolicy, Policy<R>... policies) {
5959
Duration getDelay();
6060

6161
/**
62-
* Records an execution {@code result} or {@code failure} which triggers failure handling, if needed, by the
62+
* Records an execution {@code result} or {@code exception} which triggers failure handling, if needed, by the
6363
* configured policies. If policy handling is not possible or completed, the execution is completed.
6464
*
6565
* @throws IllegalStateException if the execution is already complete
6666
*/
67-
void record(R result, Throwable failure);
67+
void record(R result, Throwable exception);
6868

6969
/**
7070
* Records an execution {@code result} which triggers failure handling, if needed, by the configured policies. If
@@ -75,10 +75,16 @@ static <R> Execution<R> of(Policy<R> outerPolicy, Policy<R>... policies) {
7575
void recordResult(R result);
7676

7777
/**
78-
* Records an execution {@code failure} which triggers failure handling, if needed, by the configured policies. If
79-
* policy handling is not possible or completed, the execution is completed.
78+
* Records an {@code exception} which triggers failure handling, if needed, by the configured policies. If policy
79+
* handling is not possible or completed, the execution is completed.
8080
*
8181
* @throws IllegalStateException if the execution is already complete
8282
*/
83+
void recordException(Throwable exception);
84+
85+
/**
86+
* @deprecated Use {@link #recordException(Throwable)} instead
87+
*/
88+
@Deprecated
8389
void recordFailure(Throwable failure);
8490
}

src/main/java/dev/failsafe/ExecutionContext.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ public interface ExecutionContext<R> {
4848
int getExecutionCount();
4949

5050
/**
51-
* Returns the last failure that was recorded else {@code null}.
51+
* Returns the last exception that was recorded else {@code null}.
5252
*/
53+
<T extends Throwable> T getLastException();
54+
55+
/**
56+
* @deprecated Use {@link #getLastException()} instead
57+
*/
58+
@Deprecated
5359
<T extends Throwable> T getLastFailure();
5460

5561
/**

src/main/java/dev/failsafe/ExecutionImpl.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,15 @@ public int getExecutionCount() {
195195

196196
@Override
197197
@SuppressWarnings("unchecked")
198-
public <T extends Throwable> T getLastFailure() {
198+
public <T extends Throwable> T getLastException() {
199199
ExecutionResult<R> r = result != null ? result : previousResult;
200-
return r == null ? null : (T) r.getFailure();
200+
return r == null ? null : (T) r.getException();
201+
}
202+
203+
@Override
204+
@Deprecated
205+
public <T extends Throwable> T getLastFailure() {
206+
return getLastException();
201207
}
202208

203209
@Override
@@ -230,6 +236,6 @@ public boolean isRetry() {
230236
@Override
231237
public String toString() {
232238
return "[" + "attempts=" + attempts + ", executions=" + executions + ", lastResult=" + getLastResult()
233-
+ ", lastFailure=" + getLastFailure() + ']';
239+
+ ", lastException=" + getLastException() + ']';
234240
}
235241
}

0 commit comments

Comments
 (0)