001package org.hl7.fhir.dstu3.utils.client.network;
002
003import java.io.IOException;
004
005import okhttp3.Interceptor;
006import okhttp3.Request;
007import okhttp3.Response;
008
009/**
010 * An {@link Interceptor} for {@link okhttp3.OkHttpClient} that controls the number of times we retry a to execute a
011 * given request, before reporting a failure. This includes unsuccessful return codes and timeouts.
012 */
013public class RetryInterceptor implements Interceptor {
014
015  // Delay between retying failed requests, in millis
016  private final long RETRY_TIME = 2000;
017
018  // Maximum number of times to retry the request before failing
019  private final int maxRetry;
020
021  // Internal counter for tracking the number of times we've tried this request
022  private int retryCounter = 0;
023
024  public RetryInterceptor(int maxRetry) {
025    this.maxRetry = maxRetry;
026  }
027
028  @Override
029  public Response intercept(Interceptor.Chain chain) throws IOException {
030    Request request = chain.request();
031    Response response = null;
032
033    do {
034      try {
035        // If we are retrying a failed request that failed due to a bad response from the server, we must close it first
036        if (response != null) {
037//          System.out.println("Previous " + chain.request().method() + " attempt returned HTTP<" + (response.code())
038//            + "> from url -> " + chain.request().url() + ".");
039          response.close();
040        }
041        // System.out.println(chain.request().method() + " attempt <" + (retryCounter + 1) + "> to url -> " + chain.request().url());
042        response = chain.proceed(request);
043      } catch (IOException e) {
044        try {
045          // Include a small break in between requests.
046          Thread.sleep(RETRY_TIME);
047        } catch (InterruptedException e1) {
048          System.out.println(chain.request().method() + " to url -> " + chain.request().url() + " interrupted on try <" + retryCounter + ">");
049        }
050      } finally {
051        retryCounter++;
052      }
053    } while ((response == null || !response.isSuccessful()) && (retryCounter <= maxRetry + 1));
054
055    /*
056     * if something has gone wrong, and we are unable to complete the request, we still need to initialize the return
057     * response so we don't get a null pointer exception.
058     */
059    return response != null ? response : chain.proceed(request);
060  }
061
062}