Skip to content

Commit bfdc7d9

Browse files
committed
Clarifies the meaning of a failure vs an exception
This commit 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 8fa0904 commit bfdc7d9

Some content is hidden

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

48 files changed

+380
-308
lines changed

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

Lines changed: 10 additions & 4 deletions
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
}

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

Lines changed: 10 additions & 4 deletions
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
}

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

Lines changed: 9 additions & 3 deletions
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
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
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(CheckedBiPredicate)}.
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
3535
* {@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 failure
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>

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

Lines changed: 10 additions & 10 deletions
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
*

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

Lines changed: 4 additions & 4 deletions
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
/**

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

Lines changed: 10 additions & 4 deletions
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
}

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

Lines changed: 7 additions & 1 deletion
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
/**

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

Lines changed: 9 additions & 3 deletions
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
}

core/src/main/java/dev/failsafe/FailsafeExecutor.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public <P extends Policy<R>> FailsafeExecutor<R> compose(P innerPolicy) {
106106
*
107107
* @throws NullPointerException if the {@code supplier} is null
108108
* @throws FailsafeException if the {@code supplier} fails with a checked Exception. {@link
109-
* FailsafeException#getCause()} can be used to learn the checked exception that caused the failure.
109+
* FailsafeException#getCause()} can be used to learn the underlying checked exception
110110
* @throws TimeoutExceededException if the execution fails because a {@link Timeout} is exceeded.
111111
* @throws CircuitBreakerOpenException if the execution fails because a {@link CircuitBreaker} is open.
112112
* @throws RateLimitExceededException if the execution fails because a {@link RateLimiter} is exceeded.
@@ -120,7 +120,7 @@ public <T extends R> T get(CheckedSupplier<T> supplier) {
120120
*
121121
* @throws NullPointerException if the {@code supplier} is null
122122
* @throws FailsafeException if the {@code supplier} fails with a checked Exception. {@link
123-
* FailsafeException#getCause()} can be used to learn the checked exception that caused the failure.
123+
* FailsafeException#getCause()} can be used to learn the underlying checked exception
124124
* @throws TimeoutExceededException if the execution fails because a {@link Timeout} is exceeded.
125125
* @throws CircuitBreakerOpenException if the execution fails because a {@link CircuitBreaker} is open.
126126
* @throws RateLimitExceededException if the execution fails because a {@link RateLimiter} is exceeded.
@@ -173,8 +173,8 @@ public <T extends R> CompletableFuture<T> getAsync(ContextualSupplier<T, T> supp
173173
* Executes the {@code runnable} asynchronously until a successful result is recorded or the configured policies are
174174
* exceeded. Executions must be recorded via one of the {@code AsyncExecution.record} methods which will trigger
175175
* failure handling, if needed, by the configured policies, else the resulting {@link CompletableFuture} will be
176-
* completed. Any exception that is thrown from the {@code runnable} will automatically be recorded via {@code
177-
* AsyncExecution.recordFailure}.
176+
* completed. Any exception that is thrown from the {@code runnable} will automatically be recorded via {@link
177+
* AsyncExecution#recordException(Throwable)}.
178178
* </p>
179179
* <ul>
180180
* <li>If the execution fails because a {@link Timeout} is exceeded, the resulting future is completed exceptionally
@@ -241,7 +241,7 @@ public <T extends R> CompletableFuture<T> getStageAsync(
241241
*
242242
* @throws NullPointerException if the {@code runnable} is null
243243
* @throws FailsafeException if the {@code runnable} fails with a checked Exception. {@link
244-
* FailsafeException#getCause()} can be used to learn the checked exception that caused the failure.
244+
* FailsafeException#getCause()} can be used to learn the underlying checked exception
245245
* @throws TimeoutExceededException if the execution fails because a {@link Timeout} is exceeded.
246246
* @throws CircuitBreakerOpenException if the execution fails because a {@link CircuitBreaker} is open.
247247
* @throws RateLimitExceededException if the execution fails because a {@link RateLimiter} is exceeded.
@@ -255,7 +255,7 @@ public void run(CheckedRunnable runnable) {
255255
*
256256
* @throws NullPointerException if the {@code runnable} is null
257257
* @throws FailsafeException if the {@code runnable} fails with a checked Exception. {@link
258-
* FailsafeException#getCause()} can be used to learn the checked exception that caused the failure.
258+
* FailsafeException#getCause()} can be used to learn the underlying checked exception
259259
* @throws TimeoutExceededException if the execution fails because a {@link Timeout} is exceeded.
260260
* @throws CircuitBreakerOpenException if the execution fails because a {@link CircuitBreaker} is open.
261261
* @throws RateLimitExceededException if the execution fails because a {@link RateLimiter} is exceeded.
@@ -306,8 +306,8 @@ public CompletableFuture<Void> runAsync(ContextualRunnable<Void> runnable) {
306306
* Executes the {@code runnable} asynchronously until a successful result is recorded or the configured policies are
307307
* exceeded. Executions must be recorded via one of the {@code AsyncExecution.record} methods which will trigger
308308
* failure handling, if needed, by the configured policies, else the resulting {@link CompletableFuture} will be
309-
* completed. Any exception that is thrown from the {@code runnable} will automatically be recorded via {@code
310-
* AsyncExecution.recordFailure}.
309+
* completed. Any exception that is thrown from the {@code runnable} will automatically be recorded via {@link
310+
* AsyncExecution#recordException(Throwable)}.
311311
* </p>
312312
* <ul>
313313
* <li>If the execution fails because a {@link Timeout} is exceeded, the resulting future is completed exceptionally
@@ -436,13 +436,13 @@ public FailsafeExecutor<R> with(Scheduler scheduler) {
436436
private <T> T call(ContextualSupplier<T, T> innerSupplier) {
437437
SyncExecutionImpl<T> execution = new SyncExecutionImpl(this, scheduler, Functions.get(innerSupplier, executor));
438438
ExecutionResult<T> result = execution.executeSync();
439-
Throwable failure = result.getFailure();
440-
if (failure != null) {
441-
if (failure instanceof RuntimeException)
442-
throw (RuntimeException) failure;
443-
if (failure instanceof Error)
444-
throw (Error) failure;
445-
throw new FailsafeException(failure);
439+
Throwable exception = result.getException();
440+
if (exception != null) {
441+
if (exception instanceof RuntimeException)
442+
throw (RuntimeException) exception;
443+
if (exception instanceof Error)
444+
throw (Error) exception;
445+
throw new FailsafeException(exception);
446446
}
447447
return result.getResult();
448448
}

0 commit comments

Comments
 (0)