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.

+3


source to share


1 answer


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.

+2


source







All Articles