Skip to content

Commit c446fae

Browse files
committed
Changed FailsafeExecutor.getAsyncExecution to accept an AsyncRunnable
1 parent 9ae6438 commit c446fae

File tree

6 files changed

+30
-59
lines changed

6 files changed

+30
-59
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
### API Changes
44

5-
- Added a generic result type `R` to `ExecutionContext`, `Execution` and `AsyncExecution`. This ensures that result types are unified across the API. It does mean that there are a few minor breaking changes to the API:
6-
- `ContextualSupplier` and `AsyncSupplier` now have an additional result type parameter `R`. Normally these types are used as lambda parameters where the type is inferred, so most users should not be impacted. But any explicit generic declaration of these types will not compile until the new parameter is added.
5+
- Added a generic result type `R` to `ExecutionContext`, `Execution`, `AsyncExecution`, and `AsyncRunnable`. This ensures that result types are unified across the API. It does mean that there are a few minor breaking changes to the API:
6+
- `ContextualSupplier` now has an additional result type parameter `R`. Normally this type is used as lambda parameters where the type is inferred, so most users should not be impacted. But any explicit generic declaration of this type will not compile until the new parameter is added.
77
- `PolicyExecutor`, which is part of the SPI, now accepts an additional result type parameter `R`. This is only relevant for SPI users who are implementing their own Policies.
8+
- Changed `FailsafeExecutor.getAsyncExecution` to accept `AsyncRunnable` instead of `AsyncSupplier`. This is a breaking change for any `getAsyncExecution` calls, but the fix is to simply remove any `return` statement. The reason for this change is that the provided object does not need to return a result since the result will already be passed asynchronously to one of the `AsyncExecution` `complete` or `retry` methods.
89

910
# 2.4.3
1011

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ public <T extends R> CompletableFuture<T> getAsync(ContextualSupplier<T, T> supp
135135
* @throws NullPointerException if the {@code supplier} is null
136136
* @throws RejectedExecutionException if the {@code supplier} cannot be scheduled for execution
137137
*/
138-
public <T extends R> CompletableFuture<T> getAsyncExecution(AsyncSupplier<T, T> supplier) {
139-
return callAsync(execution -> getPromiseExecution(supplier, execution), true);
138+
public <T extends R> CompletableFuture<T> getAsyncExecution(AsyncRunnable<T> runnable) {
139+
return callAsync(execution -> getPromiseExecution(runnable, execution), true);
140140
}
141141

142142
/**
@@ -277,8 +277,8 @@ public CompletableFuture<Void> runAsync(ContextualRunnable runnable) {
277277
* @throws NullPointerException if the {@code runnable} is null
278278
* @throws RejectedExecutionException if the {@code runnable} cannot be scheduled for execution
279279
*/
280-
public CompletableFuture<Void> runAsyncExecution(AsyncRunnable runnable) {
281-
return callAsync(execution -> getPromiseExecution(toAsyncSupplier(runnable), execution), true);
280+
public CompletableFuture<Void> runAsyncExecution(AsyncRunnable<Void> runnable) {
281+
return callAsync(execution -> getPromiseExecution(runnable, execution), true);
282282
}
283283

284284
/**

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,21 @@ static <R> Supplier<CompletableFuture<ExecutionResult>> getPromiseAsync(
132132
}
133133

134134
/**
135-
* Returns a Supplier that pre-executes the {@code execution}, applies the {@code supplier}, and attempts to complete
136-
* the {@code execution} if a failure occurs. Locks to ensure the resulting supplier cannot be applied multiple times
135+
* Returns a Supplier that pre-executes the {@code execution}, runs the {@code runnable}, and attempts to complete the
136+
* {@code execution} if a failure occurs. Locks to ensure the resulting supplier cannot be applied multiple times
137137
* concurrently.
138138
*
139139
* @param <R> result type
140140
*/
141-
static <R> Supplier<CompletableFuture<ExecutionResult>> getPromiseExecution(AsyncSupplier<R, R> supplier,
141+
static <R> Supplier<CompletableFuture<ExecutionResult>> getPromiseExecution(AsyncRunnable<R> runnable,
142142
AsyncExecution<R> execution) {
143-
Assert.notNull(supplier, "supplier");
143+
Assert.notNull(runnable, "runnable");
144144
return new Supplier<CompletableFuture<ExecutionResult>>() {
145145
@Override
146146
public synchronized CompletableFuture<ExecutionResult> get() {
147147
try {
148148
execution.preExecute();
149-
supplier.get(execution);
149+
runnable.run(execution);
150150
} catch (Throwable e) {
151151
execution.completeOrHandle(null, e);
152152
}
@@ -229,14 +229,6 @@ static <R> Supplier<CompletableFuture<ExecutionResult>> getPromiseOfStageExecuti
229229
};
230230
}
231231

232-
static AsyncSupplier<Void, Void> toAsyncSupplier(AsyncRunnable runnable) {
233-
Assert.notNull(runnable, "runnable");
234-
return execution -> {
235-
runnable.run(execution);
236-
return null;
237-
};
238-
}
239-
240232
/**
241233
* Returns a SettableSupplier that supplies the set value once then uses the {@code supplier} for subsequent calls.
242234
*

src/main/java/net/jodah/failsafe/function/AsyncRunnable.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919

2020
/**
2121
* A Runnable that manually triggers asynchronous retries or completion via an asynchronous execution.
22-
*
22+
*
23+
* @param <R> result type
2324
* @author Jonathan Halterman
2425
*/
2526
@FunctionalInterface
26-
public interface AsyncRunnable {
27-
void run(AsyncExecution<Void> execution) throws Exception;
27+
public interface AsyncRunnable<R> {
28+
void run(AsyncExecution<R> execution) throws Exception;
2829
}

src/test/java/net/jodah/failsafe/AsyncFailsafeTest.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,17 @@ public void shouldGetAsyncContextual() throws Throwable {
178178
}
179179

180180
public void shouldGetAsyncExecution() throws Throwable {
181-
assertGetAsync((AsyncSupplier<?, ?>) exec -> {
181+
assertGetAsync((AsyncRunnable<?>) exec -> {
182182
try {
183183
boolean result = service.connect();
184184
if (!exec.complete(result))
185185
exec.retry();
186-
return result;
187186
} catch (Exception failure) {
188187
// Alternate between automatic and manual retries
189188
if (exec.getAttemptCount() % 2 == 0)
190189
throw failure;
191190
if (!exec.retryOn(failure))
192191
throw failure;
193-
return null;
194192
}
195193
});
196194
}
@@ -389,10 +387,9 @@ public void shouldCancelOnGetAsyncWithTimeout() throws Throwable {
389387
}
390388

391389
public void shouldCancelOnGetAsyncExecution() throws Throwable {
392-
assertCancel(executor -> getAsync(executor, (AsyncSupplier<?, ?>) (e) -> {
390+
assertCancel(executor -> getAsync(executor, (AsyncRunnable<?>) (e) -> {
393391
Thread.sleep(1000);
394392
e.complete();
395-
return null;
396393
}), retryAlways);
397394
}
398395

@@ -435,7 +432,6 @@ public void shouldManuallyRetryAndComplete() throws Throwable {
435432
exec.retryOn(new ConnectException());
436433
else
437434
exec.complete(true);
438-
return true;
439435
});
440436
waiter.await(3000);
441437
}
@@ -504,7 +500,6 @@ public void shouldTimeoutAndRetry() throws Throwable {
504500
Thread.sleep(100);
505501
if (!exec.complete(false))
506502
exec.retry();
507-
return null;
508503
});
509504

510505
waiter.await(1000);
@@ -593,13 +588,14 @@ public void shouldSupportCovariance() {
593588
.getAsync(() -> fastService);
594589
}
595590

591+
@SuppressWarnings("unchecked")
596592
private Future<?> runAsync(FailsafeExecutor<?> failsafe, Object runnable) {
597593
if (runnable instanceof CheckedRunnable)
598594
return failsafe.runAsync((CheckedRunnable) runnable);
599595
else if (runnable instanceof ContextualRunnable)
600596
return failsafe.runAsync((ContextualRunnable) runnable);
601597
else
602-
return failsafe.runAsyncExecution((AsyncRunnable) runnable);
598+
return failsafe.runAsyncExecution((AsyncRunnable<Void>) runnable);
603599
}
604600

605601
@SuppressWarnings("unchecked")
@@ -609,7 +605,7 @@ private <T> Future<T> getAsync(FailsafeExecutor<T> failsafe, Object supplier) {
609605
else if (supplier instanceof ContextualSupplier)
610606
return failsafe.getAsync((ContextualSupplier<T, T>) supplier);
611607
else
612-
return failsafe.getAsyncExecution((AsyncSupplier<T, T>) supplier);
608+
return failsafe.getAsyncExecution((AsyncRunnable<T>) supplier);
613609
}
614610

615611
@SuppressWarnings({ "unchecked", "rawtypes" })

src/test/java/net/jodah/failsafe/Testing.java

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,10 @@ private static <T> void testSyncAndAsyncInternal(boolean testSync, FailsafeExecu
389389
if (given != null)
390390
given.run();
391391
if (expectedExceptions.length == 0) {
392-
T result = Testing.unwrapExceptions(() -> failsafe.onComplete(setCompletedEventFn::accept).get(when));
392+
T result = Testing.unwrapExceptions(() -> failsafe.onComplete(setCompletedEventFn).get(when));
393393
assertEquals(result, expectedResult);
394394
} else
395-
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn::accept).get(when), expectedExceptions);
395+
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn).get(when), expectedExceptions);
396396
postTestFn.run();
397397
}
398398

@@ -401,47 +401,28 @@ private static <T> void testSyncAndAsyncInternal(boolean testSync, FailsafeExecu
401401
if (given != null)
402402
given.run();
403403
if (expectedExceptions.length == 0) {
404-
T result = Testing.unwrapExceptions(() -> failsafe.onComplete(setCompletedEventFn::accept).getAsync(when).get());
404+
T result = Testing.unwrapExceptions(() -> failsafe.onComplete(setCompletedEventFn).getAsync(when).get());
405405
assertEquals(result, expectedResult);
406406
} else {
407407
expected.add(0, ExecutionException.class);
408-
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn::accept).getAsync(when).get(), expected);
408+
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn).getAsync(when).get(), expected);
409409
}
410410
postTestFn.run();
411411
}
412412

413-
public static <T> void testAsyncExecutionSuccess(FailsafeExecutor<T> failsafe, AsyncRunnable when,
414-
Consumer<ExecutionCompletedEvent<T>> then, T expectedResult) {
415-
AsyncSupplier supplier = ex -> {
416-
when.run(ex);
417-
return null;
418-
};
419-
testAsyncExecutionInternal(failsafe, supplier, then, expectedResult);
420-
}
421-
422-
public static <T> void testAsyncExecutionSuccess(FailsafeExecutor<T> failsafe, AsyncSupplier<T, T> when,
413+
public static <T> void testAsyncExecutionSuccess(FailsafeExecutor<T> failsafe, AsyncRunnable<T> when,
423414
Consumer<ExecutionCompletedEvent<T>> then, T expectedResult) {
424415
testAsyncExecutionInternal(failsafe, when, then, expectedResult);
425416
}
426417

427418
@SafeVarargs
428-
public static <T> void testAsyncExecutionFailure(FailsafeExecutor<T> failsafe, AsyncRunnable when,
429-
Consumer<ExecutionCompletedEvent<T>> then, Class<? extends Throwable>... expectedExceptions) {
430-
AsyncSupplier supplier = ex -> {
431-
when.run(ex);
432-
return null;
433-
};
434-
testAsyncExecutionInternal(failsafe, supplier, then, null, expectedExceptions);
435-
}
436-
437-
@SafeVarargs
438-
public static <T> void testAsyncExecutionFailure(FailsafeExecutor<T> failsafe, AsyncSupplier<T, T> when,
419+
public static <T> void testAsyncExecutionFailure(FailsafeExecutor<T> failsafe, AsyncRunnable<T> when,
439420
Consumer<ExecutionCompletedEvent<T>> then, Class<? extends Throwable>... expectedExceptions) {
440421
testAsyncExecutionInternal(failsafe, when, then, null, expectedExceptions);
441422
}
442423

443424
@SafeVarargs
444-
private static <T> void testAsyncExecutionInternal(FailsafeExecutor<T> failsafe, AsyncSupplier<T, T> when,
425+
private static <T> void testAsyncExecutionInternal(FailsafeExecutor<T> failsafe, AsyncRunnable<T> when,
445426
Consumer<ExecutionCompletedEvent<T>> then, T expectedResult, Class<? extends Throwable>... expectedExceptions) {
446427

447428
AtomicReference<ExecutionCompletedEvent<T>> completedEventRef = new AtomicReference<>();
@@ -459,13 +440,13 @@ private static <T> void testAsyncExecutionInternal(FailsafeExecutor<T> failsafe,
459440
System.out.println("\nRunning async execution test");
460441
if (expectedExceptions.length == 0) {
461442
T result = Testing.unwrapExceptions(
462-
() -> failsafe.onComplete(setCompletedEventFn::accept).getAsyncExecution(when).get());
443+
() -> failsafe.onComplete(setCompletedEventFn).getAsyncExecution(when).get());
463444
assertEquals(result, expectedResult);
464445
} else {
465446
List<Class<? extends Throwable>> expected = new LinkedList<>();
466447
Collections.addAll(expected, expectedExceptions);
467448
expected.add(0, ExecutionException.class);
468-
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn::accept).getAsyncExecution(when).get(),
449+
Asserts.assertThrows(() -> failsafe.onComplete(setCompletedEventFn).getAsyncExecution(when).get(),
469450
expected);
470451
}
471452
postTestFn.run();

0 commit comments

Comments
 (0)