Skip to content

Commit 0ef7c41

Browse files
authored
Issue ReactiveX#331: Fixed Retry.decorateCallable. It handled only RuntimeExce… (ReactiveX#389)
* Issue ReactiveX#331: Fixed Retry.decorateCallable. It handled only RuntimeExceptions, but should handle Exceptions instead. * Issue ReactiveX#331: CircuitBreaker not handle java.lang.Error, but only java.lang.Exception.
1 parent 462960f commit 0ef7c41

File tree

3 files changed

+72
-48
lines changed

3 files changed

+72
-48
lines changed

resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/CircuitBreaker.java

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -404,10 +404,11 @@ static <T> CheckedFunction0<T> decorateCheckedSupplier(CircuitBreaker circuitBre
404404
long durationInNanos = System.nanoTime() - start;
405405
circuitBreaker.onSuccess(durationInNanos);
406406
return returnValue;
407-
} catch (Throwable throwable) {
407+
} catch (Exception exception) {
408+
// Do not handle java.lang.Error
408409
long durationInNanos = System.nanoTime() - start;
409-
circuitBreaker.onError(durationInNanos, throwable);
410-
throw throwable;
410+
circuitBreaker.onError(durationInNanos, exception);
411+
throw exception;
411412
}
412413
};
413414
}
@@ -439,12 +440,15 @@ static <T> Supplier<CompletionStage<T>> decorateCompletionStage(
439440
try {
440441
supplier.get().whenComplete((result, throwable) -> {
441442
long durationInNanos = System.nanoTime() - start;
442-
if (throwable != null) {
443-
circuitBreaker.onError(durationInNanos, throwable);
444-
promise.completeExceptionally(throwable);
445-
} else {
443+
if (result != null) {
446444
circuitBreaker.onSuccess(durationInNanos);
447445
promise.complete(result);
446+
} else if (throwable instanceof Exception) {
447+
circuitBreaker.onError(durationInNanos, throwable);
448+
promise.completeExceptionally(throwable);
449+
} else{
450+
// Do not handle java.lang.Error
451+
promise.completeExceptionally(throwable);
448452
}
449453
});
450454
} catch (Throwable throwable) {
@@ -474,10 +478,11 @@ static CheckedRunnable decorateCheckedRunnable(CircuitBreaker circuitBreaker, Ch
474478
runnable.run();
475479
long durationInNanos = System.nanoTime() - start;
476480
circuitBreaker.onSuccess(durationInNanos);
477-
} catch (Throwable throwable){
481+
} catch (Exception exception){
482+
// Do not handle java.lang.Error
478483
long durationInNanos = System.nanoTime() - start;
479-
circuitBreaker.onError(durationInNanos, throwable);
480-
throw throwable;
484+
circuitBreaker.onError(durationInNanos, exception);
485+
throw exception;
481486
}
482487
};
483488
}
@@ -500,10 +505,11 @@ static <T> Callable<T> decorateCallable(CircuitBreaker circuitBreaker, Callable<
500505
long durationInNanos = System.nanoTime() - start;
501506
circuitBreaker.onSuccess(durationInNanos);
502507
return returnValue;
503-
} catch (Throwable throwable) {
508+
} catch (Exception exception) {
509+
// Do not handle java.lang.Error
504510
long durationInNanos = System.nanoTime() - start;
505-
circuitBreaker.onError(durationInNanos, throwable);
506-
throw throwable;
511+
circuitBreaker.onError(durationInNanos, exception);
512+
throw exception;
507513
}
508514
};
509515
}
@@ -526,10 +532,11 @@ static <T> Supplier<T> decorateSupplier(CircuitBreaker circuitBreaker, Supplier<
526532
long durationInNanos = System.nanoTime() - start;
527533
circuitBreaker.onSuccess(durationInNanos);
528534
return returnValue;
529-
} catch (Throwable throwable) {
535+
} catch (Exception exception) {
536+
// Do not handle java.lang.Error
530537
long durationInNanos = System.nanoTime() - start;
531-
circuitBreaker.onError(durationInNanos, throwable);
532-
throw throwable;
538+
circuitBreaker.onError(durationInNanos, exception);
539+
throw exception;
533540
}
534541
};
535542
}
@@ -551,10 +558,11 @@ static <T> Consumer<T> decorateConsumer(CircuitBreaker circuitBreaker, Consumer<
551558
consumer.accept(t);
552559
long durationInNanos = System.nanoTime() - start;
553560
circuitBreaker.onSuccess(durationInNanos);
554-
} catch (Throwable throwable) {
561+
} catch (Exception exception) {
562+
// Do not handle java.lang.Error
555563
long durationInNanos = System.nanoTime() - start;
556-
circuitBreaker.onError(durationInNanos, throwable);
557-
throw throwable;
564+
circuitBreaker.onError(durationInNanos, exception);
565+
throw exception;
558566
}
559567
};
560568
}
@@ -576,10 +584,11 @@ static <T> CheckedConsumer<T> decorateCheckedConsumer(CircuitBreaker circuitBrea
576584
consumer.accept(t);
577585
long durationInNanos = System.nanoTime() - start;
578586
circuitBreaker.onSuccess(durationInNanos);
579-
} catch (Throwable throwable) {
587+
} catch (Exception exception) {
588+
// Do not handle java.lang.Error
580589
long durationInNanos = System.nanoTime() - start;
581-
circuitBreaker.onError(durationInNanos, throwable);
582-
throw throwable;
590+
circuitBreaker.onError(durationInNanos, exception);
591+
throw exception;
583592
}
584593
};
585594
}
@@ -600,10 +609,11 @@ static Runnable decorateRunnable(CircuitBreaker circuitBreaker, Runnable runnabl
600609
runnable.run();
601610
long durationInNanos = System.nanoTime() - start;
602611
circuitBreaker.onSuccess(durationInNanos);
603-
} catch (Throwable throwable){
612+
} catch (Exception exception){
613+
// Do not handle java.lang.Error
604614
long durationInNanos = System.nanoTime() - start;
605-
circuitBreaker.onError(durationInNanos, throwable);
606-
throw throwable;
615+
circuitBreaker.onError(durationInNanos, exception);
616+
throw exception;
607617
}
608618
};
609619
}
@@ -626,10 +636,11 @@ static <T, R> Function<T, R> decorateFunction(CircuitBreaker circuitBreaker, Fun
626636
long durationInNanos = System.nanoTime() - start;
627637
circuitBreaker.onSuccess(durationInNanos);
628638
return returnValue;
629-
} catch (Throwable throwable){
639+
} catch (Exception exception){
640+
// Do not handle java.lang.Error
630641
long durationInNanos = System.nanoTime() - start;
631-
circuitBreaker.onError(durationInNanos, throwable);
632-
throw throwable;
642+
circuitBreaker.onError(durationInNanos, exception);
643+
throw exception;
633644
}
634645
};
635646
}
@@ -652,10 +663,11 @@ static <T, R> CheckedFunction1<T, R> decorateCheckedFunction(CircuitBreaker circ
652663
long durationInNanos = System.nanoTime() - start;
653664
circuitBreaker.onSuccess(durationInNanos);
654665
return returnValue;
655-
} catch (Throwable throwable){
666+
} catch (Exception exception){
667+
// Do not handle java.lang.Error
656668
long durationInNanos = System.nanoTime() - start;
657-
circuitBreaker.onError(durationInNanos, throwable);
658-
throw throwable;
669+
circuitBreaker.onError(durationInNanos, exception);
670+
throw exception;
659671
}
660672
};
661673
}

resilience4j-retry/src/main/java/io/github/resilience4j/retry/Retry.java

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static <T> Supplier<CompletionStage<T>> decorateCompletionStage(
9292
return () -> {
9393

9494
final CompletableFuture<T> promise = new CompletableFuture<>();
95-
@SuppressWarnings("unchecked") final Runnable block = new AsyncRetryBlock<>(scheduler, retry.asyncContext(), supplier, promise);
95+
final Runnable block = new AsyncRetryBlock<>(scheduler, retry.asyncContext(), supplier, promise);
9696
block.run();
9797

9898
return promise;
@@ -109,7 +109,6 @@ static <T> Supplier<CompletionStage<T>> decorateCompletionStage(
109109
*/
110110
static <T> CheckedFunction0<T> decorateCheckedSupplier(Retry retry, CheckedFunction0<T> supplier) {
111111
return () -> {
112-
@SuppressWarnings("unchecked")
113112
Retry.Context<T> context = retry.context();
114113
do try {
115114
T result = supplier.apply();
@@ -155,7 +154,6 @@ static CheckedRunnable decorateCheckedRunnable(Retry retry, CheckedRunnable runn
155154
*/
156155
static <T, R> CheckedFunction1<T, R> decorateCheckedFunction(Retry retry, CheckedFunction1<T, R> function) {
157156
return (T t) -> {
158-
@SuppressWarnings("unchecked")
159157
Retry.Context<R> context = retry.context();
160158
do try {
161159
R result = function.apply(t);
@@ -180,7 +178,6 @@ static <T, R> CheckedFunction1<T, R> decorateCheckedFunction(Retry retry, Checke
180178
*/
181179
static <T> Supplier<T> decorateSupplier(Retry retry, Supplier<T> supplier) {
182180
return () -> {
183-
@SuppressWarnings("unchecked")
184181
Retry.Context<T> context = retry.context();
185182
do try {
186183
T result = supplier.get();
@@ -205,7 +202,6 @@ static <T> Supplier<T> decorateSupplier(Retry retry, Supplier<T> supplier) {
205202
*/
206203
static <T> Callable<T> decorateCallable(Retry retry, Callable<T> supplier) {
207204
return () -> {
208-
@SuppressWarnings("unchecked")
209205
Retry.Context<T> context = retry.context();
210206
do try {
211207
T result = supplier.call();
@@ -214,8 +210,8 @@ static <T> Callable<T> decorateCallable(Retry retry, Callable<T> supplier) {
214210
context.onSuccess();
215211
return result;
216212
}
217-
} catch (RuntimeException runtimeException) {
218-
context.onRuntimeError(runtimeException);
213+
} catch (Exception exception) {
214+
context.onError(exception);
219215
} while (true);
220216
};
221217
}
@@ -251,7 +247,6 @@ static Runnable decorateRunnable(Retry retry, Runnable runnable) {
251247
*/
252248
static <T, R> Function<T, R> decorateFunction(Retry retry, Function<T, R> function) {
253249
return (T t) -> {
254-
@SuppressWarnings("unchecked")
255250
Retry.Context<R> context = retry.context();
256251
do try {
257252
R result = function.apply(t);
@@ -278,14 +273,14 @@ static <T, R> Function<T, R> decorateFunction(Retry retry, Function<T, R> functi
278273
*
279274
* @return the retry Context
280275
*/
281-
Retry.Context context();
276+
<T> Retry.Context<T> context();
282277

283278
/**
284279
* Creates a async retry Context.
285280
*
286281
* @return the async retry Context
287282
*/
288-
Retry.AsyncContext asyncContext();
283+
<T> Retry.AsyncContext<T> asyncContext();
289284

290285
/**
291286
* Returns the RetryConfig of this Retry.
@@ -301,6 +296,18 @@ static <T, R> Function<T, R> decorateFunction(Retry retry, Function<T, R> functi
301296
*/
302297
EventPublisher getEventPublisher();
303298

299+
/**
300+
* Decorates and executes the decorated Supplier.
301+
*
302+
* @param checkedSupplier the original Supplier
303+
* @param <T> the type of results supplied by this supplier
304+
* @return the result of the decorated Supplier.
305+
* @throws Throwable if something goes wrong applying this function to the given arguments
306+
*/
307+
default <T> T executeCheckedSupplier(CheckedFunction0<T> checkedSupplier) throws Throwable {
308+
return decorateCheckedSupplier(this, checkedSupplier).apply();
309+
}
310+
304311
/**
305312
* Decorates and executes the decorated Supplier.
306313
*
@@ -429,14 +436,15 @@ interface Context<T> {
429436
* Handles a checked exception
430437
*
431438
* @param exception the exception to handle
432-
* @throws Throwable the exception
439+
* @throws Exception when retry count has exceeded
433440
*/
434-
void onError(Exception exception) throws Throwable;
441+
void onError(Exception exception) throws Exception;
435442

436443
/**
437444
* Handles a runtime exception
438445
*
439446
* @param runtimeException the exception to handle
447+
* @throws RuntimeException when retry count has exceeded
440448
*/
441449
void onRuntimeError(RuntimeException runtimeException);
442450
}
@@ -481,21 +489,24 @@ public void run() {
481489

482490
try {
483491
stage = supplier.get();
484-
} catch (Throwable t) {
492+
} catch (Exception t) {
485493
onError(t);
486494
return;
487495
}
488496

489497
stage.whenComplete((result, t) -> {
490498
if (result != null) {
491499
onResult(result);
492-
} else if (t != null) {
493-
onError(t);
500+
} else if (t instanceof Exception) {
501+
onError((Exception) t);
502+
} else{
503+
// Do not handle java.lang.Error
504+
promise.completeExceptionally(t);
494505
}
495506
});
496507
}
497508

498-
private void onError(Throwable t) {
509+
private void onError(Exception t) {
499510
final long delay = retryContext.onError(t);
500511

501512
if (delay < 1) {

resilience4j-retry/src/main/java/io/github/resilience4j/retry/internal/RetryImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public Context context() {
8686
}
8787

8888
@Override
89+
@SuppressWarnings("unchecked")
8990
public AsyncContext asyncContext() {
9091
return new AsyncContextImpl();
9192
}
@@ -147,7 +148,7 @@ public boolean onResult(T result) {
147148
return false;
148149
}
149150

150-
public void onError(Exception exception) throws Throwable {
151+
public void onError(Exception exception) throws Exception {
151152
if (exceptionPredicate.test(exception)) {
152153
lastException.set(exception);
153154
throwOrSleepAfterException();

0 commit comments

Comments
 (0)