Skip to content

Commit 15d539c

Browse files
committed
Fix Fallback.onFailedAttempt
Fixes #298
1 parent d057983 commit 15d539c

File tree

5 files changed

+59
-12
lines changed

5 files changed

+59
-12
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
# Next Minor Release
1+
# 2.4.4
2+
3+
### Bug Fixes
4+
5+
- Fixed #298 - `Fallback.onFailedAttempt` not being called correctly
26

37
### API Changes
48

src/main/java/net/jodah/failsafe/Fallback.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,8 @@ public boolean isAsync() {
220220
}
221221

222222
/**
223-
* Registers the {@code listener} to be called when an execution attempt fails. You can also use {@link
224-
* #onFailure(CheckedConsumer) onFailure} to determine when the execution attempt fails <i>and</i> and the fallback
225-
* result fails.
223+
* Registers the {@code listener} to be called when the last execution attempt prior to the fallback failed. You can
224+
* also use {@link #onFailure(CheckedConsumer) onFailure} to determine when the fallback attempt also fails.
226225
* <p>Note: Any exceptions that are thrown from within the {@code listener} are ignored.</p>
227226
*/
228227
public Fallback<R> onFailedAttempt(CheckedConsumer<? extends ExecutionAttemptedEvent<R>> listener) {

src/main/java/net/jodah/failsafe/FallbackExecutor.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ protected Supplier<ExecutionResult> supply(Supplier<ExecutionResult> supplier, S
4747
return result;
4848

4949
if (isFailure(result)) {
50+
if (failedAttemptListener != null)
51+
failedAttemptListener.handle(result, execution);
52+
5053
try {
5154
result = policy == Fallback.VOID ?
5255
result.withNonResult() :
@@ -75,6 +78,9 @@ protected Supplier<CompletableFuture<ExecutionResult>> supplyAsync(
7578
if (!isFailure(result))
7679
return postExecuteAsync(result, scheduler, future);
7780

81+
if (failedAttemptListener != null)
82+
failedAttemptListener.handle(result, execution);
83+
7884
CompletableFuture<ExecutionResult> promise = new CompletableFuture<>();
7985
Callable<R> callable = () -> {
8086
try {
@@ -113,11 +119,4 @@ protected Supplier<CompletableFuture<ExecutionResult>> supplyAsync(
113119
return promise.thenCompose(ss -> postExecuteAsync(ss, scheduler, future));
114120
});
115121
}
116-
117-
@Override
118-
protected ExecutionResult onFailure(ExecutionResult result) {
119-
if (failedAttemptListener != null)
120-
failedAttemptListener.handle(result, execution);
121-
return result;
122-
}
123122
}

src/test/java/net/jodah/failsafe/issues/Issue284Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void testFallbackSuccess() {
4444
String result = Failsafe.with(fallback).get(() -> null);
4545

4646
assertEquals(result, "hello");
47-
assertEquals(failedAttempt.get(), 0);
47+
assertEquals(failedAttempt.get(), 1);
4848
assertTrue(success.get(), "Fallback should have been successful");
4949
}
5050

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package net.jodah.failsafe.issues;
2+
3+
import net.jodah.failsafe.Failsafe;
4+
import net.jodah.failsafe.Fallback;
5+
import org.testng.annotations.BeforeMethod;
6+
import org.testng.annotations.Test;
7+
8+
import java.util.concurrent.atomic.AtomicBoolean;
9+
10+
import static org.testng.Assert.assertFalse;
11+
import static org.testng.Assert.assertTrue;
12+
13+
@Test
14+
public class Issue298Test {
15+
AtomicBoolean failedAttemptCalled = new AtomicBoolean();
16+
AtomicBoolean failureCalled = new AtomicBoolean();
17+
18+
Fallback<String> fallback = Fallback.<String>of(e -> "success")
19+
.onFailedAttempt(e -> failedAttemptCalled.set(true))
20+
.onFailure(e -> failureCalled.set(true));
21+
22+
@BeforeMethod
23+
protected void beforeMethod() {
24+
failedAttemptCalled.set(false);
25+
failureCalled.set(false);
26+
}
27+
28+
public void testSync() {
29+
Failsafe.with(fallback).get(() -> {
30+
throw new Exception();
31+
});
32+
33+
assertTrue(failedAttemptCalled.get());
34+
assertFalse(failureCalled.get());
35+
}
36+
37+
public void testAsync() throws Throwable {
38+
Failsafe.with(fallback).getAsync(() -> {
39+
throw new Exception();
40+
}).get();
41+
42+
assertTrue(failedAttemptCalled.get());
43+
assertFalse(failureCalled.get());
44+
}
45+
}

0 commit comments

Comments
 (0)