Re-install 2 + RxJava retryWhen
I am using Retrofit 2 along with RxJava 2 adapters.
Whenever the server returns 401 Unauthorized, I update the token and repeat the request:
apiCall.retryWhen(es -> es
.flatMap(e -> {
if (isUnauthorizedException(e)) {
return refreshToken();
}
return Flowable.<User>error(e);
}));
Where refreshToken is an easy way to rebuild:
public Flowable<User> refreshToken() {
return retrofitService.login(userCredentials);
}
Now I would like to limit the number of times such an update is possible. However, just adding take(1)
doesn't work because then retryWhen gets onCompleted right after onNext and cancels the request before retrying it.
Naturally, I could do take(2)
to achieve the desired effect, but this seems like a hack.
What is the most elegant way to achieve it using Rx operators? Also is there an operator with "assertion" logic (to get rid of if
on a flat map)?
Also I know that I can achieve the same using OkHttp interceptors, but I am interested in the Retrofit-RxJava solution.
source to share
There is a good example from the documentation
it repeats 3 times, each time increasing the number of seconds to wait.
ObservableSource.create((Observer<? super String> s) -> {
System.out.println("subscribing");
s.onError(new RuntimeException("always fails"));
}).retryWhen(attempts -> {
return attempts.zipWith(ObservableSource.range(1, 3),
(n, i) -> i).flatMap(i -> {
System.out.println("delay retry by " + i + " second(s)");
return ObservableSource.timer(i, TimeUnit.SECONDS);
});
}).blockingForEach(System.out::println);
Output:
- subscription
- Re-send delay by 1 second.
- retry to delay subscription for 2 seconds.
- retry to delay subscription for 3 seconds.
- signer
you can modify this example to suit your requirements.
source to share