Использование com.google.api.client.util.ExponentialBackOff для реализации общей политики повторных попыток Http

Я пытаюсь реализовать своего рода обработчик, который может факторизовать использование экспоненциального отката для http-запросов, в смысле: "если код состояния удовлетворяет некоторому условию (например, отличается от 200 и 404), повторите вызов".

Вот то, чего я достиг до сих пор, но это кажется слишком сложным, я думаю, что есть более простой способ реализовать это:

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.api.client.util.ExponentialBackOff;

public class HttpExponentialBackoffHandler<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpExponentialBackoffHandler.class);

    private ExponentialBackOff expBackoff;
    private HttpExponentialBackoffCallback<T> doOperation;

    public HttpExponentialBackoffHandler(int intervalMillis, HttpExponentialBackoffCallback<T> doOperation) {
        this.expBackoff = new ExponentialBackOff.Builder()
                .setInitialIntervalMillis(intervalMillis)
                .build();
        this.doOperation = doOperation;
    }

    public T execute() {
        int i = 1;
        long backOffMillis = ExponentialBackOff.STOP;
        HttpExponentialBackoffHandler<T>.HttpOperationResult result = null;
        do {
            LOGGER.debug("Executing {}° request", i);
            result = doOperation.doOperation();

            if(doOperation.retry(result.statusCode)) {
                try {
                    backOffMillis = expBackoff.nextBackOffMillis();
                    if(backOffMillis>0) {
                        LOGGER.debug("Going to sleep for {}", backOffMillis);
                        Thread.sleep(backOffMillis);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            i++;
        }
        while(backOffMillis!=ExponentialBackOff.STOP);

        return result.result;
    }

    public interface HttpExponentialBackoffCallback<T> {

        public HttpExponentialBackoffHandler<T>.HttpOperationResult doOperation();

        public boolean retry(int httpResponseStatusCode);

    }

    public class HttpOperationResult {

        public T result;

        public int statusCode;

        public HttpOperationResult(T result, int statusCode) {
            super();
            this.result = result;
            this.statusCode = statusCode;
        }

        public T getResult() {
            return result;
        }

        public void setResult(T result) {
            this.result = result;
        }

        public int getStatusCode() {
            return statusCode;
        }

        public void setStatusCode(int statusCode) {
            this.statusCode = statusCode;
        }

    }
}

Пример использования:

final GetPublicationDataResponse response = null;

    HttpExponentialBackoffHandler<GetPublicationDataResponse> backoffHandler = new HttpExponentialBackoffHandler<GetPublicationDataResponse>(3000, new HttpExponentialBackoffCallback<GetPublicationDataResponse>() {

        @SuppressWarnings("rawtypes")
        @Override
        public HttpExponentialBackoffHandler<GetPublicationDataResponse>.HttpOperationResult doOperation() {
            GetPublicationDataResponse response = null;
            HttpURLConnection conn = null;
            try {
                // do the call here
                ...
                if (conn.getResponseCode() == 200) {

                    response = configService.getObjectMapper().readValue(conn.getInputStream(), GetPublicationDataResponse.class);

                }

            } catch(IOException e) {
                throw new RuntimeException(e);
            }

            return new HttpOperationResult(response, conn.getResponseCode());
        }

        @Override
        public boolean retry(int httpResponseStatusCode) {
            boolean result = true;
            if(httpResponseStatusCode==200 || httpResponseStatusCode==404) {
                result = false;
            }

            return true;
        }

    });

    response = backoffHandler.execute();

    return response.getPublicationData();

NB. Я не использую HttpRequest от Google, который уже поддерживает этот механизм.

Есть ли у вас идеи улучшить и реорганизовать этот код, чтобы сделать его проще?

0 ответов

Другие вопросы по тегам