We have the following methods which we have recently migrated from rx-java to rx-java2:
@Override
public Observable<FooResponse> doFoo(String id) {
return api.doFoo(id)
.map(Response::body)
.retryWhen(errors -> shouldRetry(
errors
)
)
.switchIfEmpty(
Observable.error(new FooTimeoutException(id)));
}
private Observable<Long> shouldRetry(Observable<? extends Throwable> errors) {
return errors.filter(e -> e instanceof ClientException)
.cast(ClientException.class)
.map(ClientException::getStatusCode)
.flatMap(statusCode -> statusCode == 1 || statusCode == 2
? Observable.just(statusCode)
: errors.flatMap(Observable::error)
)
.zipWith(Observable.range(1, 3), (n, i) -> i)
.doOnNext(retryCount -> log.info("Retrying {}", retryCount))
.flatMap(retryCount -> Observable.timer(500, TimeUnit.MILLISECONDS));
}
This method should perform a retry when api.doFoo returns an exception of type ClientException with status code 1 or 2.
This worked fine in rx-java, but now that we're migrating to rx-java2, we're seeing that our unit tests hangs when the status code is not 1 or 2.
Has the syntax around this functionality changed between 1 and 2? How should this be structured?
I've resolved this issue with a bit of a refactor. My solution now looks like this:
I'm not totally sure why this works, as the only real difference is that we're not filtering the errors out, but it seems to have done the job.