19

I am setting the retry on connection failure option for OkHttpClient.

client = new OkHttpClient();
client.setRetryOnConnectionFailure(true);

I will like to know how many times it will keep trying. Looking at the source code I did not see any maximum limit. How do I configure the client to stop trying after a few attempts?

RajV
  • 6,860
  • 8
  • 44
  • 62

5 Answers5

10

There are more docs here https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.Builder.html#retryOnConnectionFailure-boolean-

Configure this client to retry or not when a connectivity problem is encountered. By default, this client silently recovers from the following problems:

  • Unreachable IP addresses. If the URL's host has multiple IP addresses, failure to reach any individual IP address doesn't fail the overall request. This can increase availability of multi-homed services.
  • Stale pooled connections. The ConnectionPool reuses sockets to decrease request latency, but these connections will occasionally time out.

  • Unreachable proxy servers. A ProxySelector can be used to attempt multiple proxy servers in sequence, eventually falling back to a direct connection.

Set this to false to avoid retrying requests when doing so is destructive. In this case the calling application should do its own recovery of connectivity failures.

But generally, I believe it is intended to retry when there is an existing stale connection, or alternate paths that can be retried. Not to retry exactly the same thing indefinitely.

Also see ConnectionSpecSelector.connectionFailed

Pang
  • 9,564
  • 146
  • 81
  • 122
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
  • This is my understanding too. In addition, it will also retry a failed SSL handshake. But it does not seem to retry an outright TCP connection failure. – RajV Jun 17 '16 at 20:28
5

There's no in built method to set the maximum limit, but you can add an interceptor like below.

client.interceptors().add(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // try the request
        Response response = chain.proceed(request);

        int tryCount = 0;
        int maxLimit = 3; //Set your max limit here

        while (!response.isSuccessful() && tryCount < maxLimit) {

            Log.d("intercept", "Request failed - " + tryCount);

            tryCount++;

            // retry the request
            response = chain.proceed(request);
        }

        // otherwise just pass the original response on
        return response;
    }
});

More detail on interceptos can be found here.

Prerak Sola
  • 9,517
  • 7
  • 36
  • 67
  • response.isSuccessful() checks for HTTP status code. Will that work for connection failure? – RajV Jun 17 '16 at 14:23
  • Yes. if the response code is 2xx or 3xx, `isSuccessful()` will return `true`. For rest, it will return `false`. And connection failures are mostly 4xx, so it should work. – Prerak Sola Jun 17 '16 at 14:26
  • 2
    TCP connection failure means no HTTP request could be sent or response obtained. I am not sure how the status code will be 4xx. – RajV Jun 17 '16 at 15:01
  • RajV's right,the chain.proceed(request) will throw IOE exception instead of return false when the connection is failure, so Prerak Sola's answer can only retry based on the connection is success – Liangliang Sha Aug 15 '16 at 08:25
  • i think this code might throw error to first close the response then make new request. – Ahmad Shahwaiz Aug 16 '21 at 08:28
5

I made an workaround below:

@Override
public Response intercept(Chain chain) throws IOException {
  Request request = chain.request();
  // try the request
  Response response = doRequest(chain,request);
  int tryCount = 0;
  while (response == null && tryCount <= RetryCount) {
    String url = request.url().toString();
    url = switchServer(url);
    Request newRequest = request.newBuilder().url(url).build();
    tryCount++;
    // retry the request
    response = doRequest(chain,newRequest);
  }
  if(response == null){//important ,should throw an exception here
      throw new IOException();
  }
  return response;
}

private Response doRequest(Chain chain,Request request){
  Response response = null;
  try{
      response = chain.proceed(request);
  }catch (Exception e){
  }
  return response;
}
3

According to source code of RetryAndFollowUpInterceptor it is 20

  /**
   * How many redirects and auth challenges should we attempt? Chrome follows 21 redirects; Firefox,
   * curl, and wget follow 20; Safari follows 16; and HTTP/1.0 recommends 5.
   */
  private static final int MAX_FOLLOW_UPS = 20;

Source: https://github.com/square/okhttp/blob/b9267b0ce7a11440ccdd6b3e7d70c4ab9710a144/okhttp/src/jvmMain/kotlin/okhttp3/internal/http/RetryAndFollowUpInterceptor.kt#L326

android_dev
  • 3,886
  • 1
  • 33
  • 52
0

OkHttp will potentially repeat your requests on a slow/unreliable connection “aggressively” until it succeeds. This is done for GET, POST or any other type of requests

Rajesh N
  • 6,198
  • 2
  • 47
  • 58