The issue with modifiable request on OkHttp silent retry

Viewed 124

In my scenario, our backend wants to get a unique ID with any request but I read that "OkHttp will potentially repeat your requests on a slow/unreliable connection 'aggressively' until it succeeds." from here and some OkHttp issues. I know I can disable the retry mechanism with retryOnConnectionFailure(false) but I want to enable it to handle connectivity problems. Exactly what I want is, modify the request before silent retry. Can I intercept before sending a silent request?

2 Answers

If you add a networkInterceptor then you should have roughly 1:1 with the calls made to your backend. A normal interceptor may not involve an actual request if you get a cache hit, and it won't see all the retries. So add a networkInterceptor which will get called for each route chosen.

The multiple attempts come from both alternative routes (multiple DNS results) and safely retrying some calls based on the HTTP request or server response code that indicate it is safe to do so.

See https://square.github.io/okhttp/interceptors/ for information.

Choosing between application and network interceptors

Each interceptor chain has relative merits.

Application interceptors

Don’t need to worry about intermediate responses like redirects and retries.
Are always invoked once, even if the HTTP response is served from the cache.
Observe the application’s original intent. Unconcerned with OkHttp-injected headers like If-None-Match.
Permitted to short-circuit and not call Chain.proceed().
Permitted to retry and make multiple calls to Chain.proceed().
Can adjust Call timeouts using withConnectTimeout, withReadTimeout, withWriteTimeout.

Network Interceptors

Able to operate on intermediate responses like redirects and retries.
Not invoked for cached responses that short-circuit the network.
Observe the data just as it will be transmitted over the network.
Access to the Connection that carries the request.

I think you can solve this process with Interceptor. When a server cannot be connected, you can connect to another server.

@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;
    }
Related