Reputation: 1502
Ive created an interceptor. In some cases, I want to retry the request 'n' number of time how do i do this?
class NetworkErrorHandler constructor(): Interceptor {
//Central error handling block for errors which has impact all over the app
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
var response = chain.proceed(request)
return
when (response.code) {
401 -> {
response
}
200 ->{
response
}
else -> {
var tryCount = 0
while (tryCount < 3) {
try {
response = chain.proceed(request)
tryCount++
}catch (e: java.lang.Exception){
tryCount++
}
}
response
}
}
}
}
It gives me this error:
Suppressed: java.lang.IllegalStateException: network interceptor must call proceed() exactly once
Do I have to do this here if yes, then how?
Upvotes: 3
Views: 11695
Reputation: 101
Use .interceptors()
to use Application Interceptor
instead of .networkInterceptors()
which are allowed to call .proceed()
more than once.
More information: https://square.github.io/okhttp/interceptors/
Upvotes: 6
Reputation: 479
This is how I approached it:
@Slf4j
public class HttpRetryInterceptor implements Interceptor {
@Override
public @NotNull Response intercept(Chain chain) throws IOException {
log.error("Making request for the first time.");
var request = chain.request();
Response response = null;
boolean responseOK = false;
byte tryCount = 0;
while (!responseOK && tryCount < 3) {
try {
Thread.sleep(5000 * tryCount);
response = chain.proceed(request);
log.info("Response is: {}",response);
log.info("Response message: {}",response.message());
responseOK = response.isSuccessful();
}catch (Exception e){
e.printStackTrace();
log.error("Request was not successful: {} . Retrying." , tryCount);
}finally{
assert response != null;
response.close();
tryCount++;
}
}
return response != null ? response : chain.proceed(request);
}
}
And then I added my Interceptor to my client with something like : new OkHttpClient.Builder().addInterceptor(new HttpRetryInterceptor()).build()
Upvotes: 2
Reputation: 1502
So i was able to make another call from the interceptor by using this line
response.close()
chain.call().clone().execute()
Full code according to the question:
//Central error handling block for errors which has impact all over the app
class NetworkErrorHandler constructor(): Interceptor {
var tryCount = 0
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
var response = chain.proceed(request)
return
when(response.code) {
401 - > {
response
}
200 - > {
response
}
else - > {
if (tryCount < 3) {
Thread.sleep(2000)
tryCount++
response.close()
chain.call().clone().execute()
}
response.newBuilder()
.code(401) // Whatever code
.body("".toResponseBody(null)) // Whatever body
.protocol(Protocol.HTTP_2)
.message("Network Error")
.request(chain.request())
.build()
}
}
}
Upvotes: 1
Reputation: 792
I think you guided yourself from this other question How to retry HTTP requests with OkHttp/Retrofit? (If not, I suggest you do). The problem on your code is that your while is restricted only by trycount, but not by the result of the response. Try adding the validation regarding the status of the response in there too, so it doesn't execute the .proceed method two times in parallel.
// try the request
Response response = chain.proceed(request);
int tryCount = 0;
while (!response.isSuccessful() && tryCount < 3) {
Upvotes: 0