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