Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do We Get the Throwable After retryWhen() Stops Retrying?

Tags:

rx-java2

  private String stringResult=null;
  private Throwable throwableResult=null;

  @Test
  public void whereIsTheThrowable() {
    Observable.just("foo")
      .map(this::justBlowUp)
      .retryWhen(errors -> errors.zipWith(Observable.range(1, 3), (n, i) -> i))
      .subscribe(s -> stringResult=s, throwable -> throwableResult=throwable);

    assertNull(stringResult);
    assertNotNull(throwableResult);
  }

  private String justBlowUp(String s) {
    throw new RuntimeException();
  }

That test fails with RxJava 2.1.7. retryWhen() appears to consume the Throwable, even after it no longer retries. The subscribe() lambda does not get any Throwable. While this test is silly (justBlowUp() just blows up), you can imagine an Observable chain where the work usually succeeds, only occasionally fails, and seldom fails four times in succession. However, in that case, it would be useful to have the Throwable for logging purposes.

retryUntil() does allow subscribe() to get the final Throwable... but then in retryUntil() we do not have the Throwable at all and cannot make decisions on it (e.g., retry N times if it seems to be an Internet connectivity error, but fail fast for everything else). retryWhen() seems to be the more powerful option, but how do we get the final Throwable, after retryWhen() stops retrying?

I could use a field to hold the Throwable, set inside the retryWhen() logic, but it feels like there should be a more idiomatic solution.

like image 613
CommonsWare Avatar asked Jun 14 '26 00:06

CommonsWare


1 Answers

retryWhen treats the handler's completion as indicator for completing normally, therefore, the handler should fail after the retry options have been exhausted:

Observable.just("foo")
.map(this::justBlowUp)
.retryWhen(errors -> errors.flatMap(new Function<Throwable, Observable<Integer>>() {
    int count;
    @Override
    public Observable<Integer> apply(Throwable error) {
        if (count++ < 3) {
            return Observable.just(count);
        }
        return Observable.error(error);
    }
}))
.test()
.assertFailure(RuntimeException.class);
like image 156
akarnokd Avatar answered Jun 17 '26 23:06

akarnokd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!