io.deepsense.neptune.clientlibrary.services.apiservice.retries.IncreasingTimeoutsRequestRetryStrategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neptune-client-library Show documentation
Show all versions of neptune-client-library Show documentation
Enables integration with Neptune in your Java code
/**
* Copyright (c) 2016, CodiLime Inc.
*/
package io.deepsense.neptune.clientlibrary.services.apiservice.retries;
import io.deepsense.neptune.apiclient.ApiException;
import io.deepsense.neptune.clientlibrary.config.internal.RequestRetryConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ThreadLocalRandom;
public class IncreasingTimeoutsRequestRetryStrategy implements RequestRetryStrategy {
private static final Logger logger = LoggerFactory.getLogger(IncreasingTimeoutsRequestRetryStrategy.class);
// Response code 0 is returned by Swagger on various types of connection failure.
private static final Collection responseCodesToIgnore = Arrays.asList(0, 500, 502, 503, 504);
private final long retryTimeoutCap;
private int attemptCounter = 0;
public IncreasingTimeoutsRequestRetryStrategy(RequestRetryConfiguration configuration) {
this.retryTimeoutCap = configuration.getMaxTimeoutBetweenRequestsInMillis();
}
@Override
public RequestRetryOutcome retryRequest(Request request) throws ApiException {
incrementAttemptCounter();
if (previousRequestFailed()) {
System.out.println("Connection lost. Retrying...");
}
try {
T value = request.send();
return requestSucceeded(value);
} catch (ApiException exc) {
return handleApiException(exc);
} catch (Exception exc) {
return requestFailed();
}
}
private RequestRetryOutcome handleApiException(ApiException exc) throws ApiException {
if (responseCodesToIgnore.contains(exc.getCode())) {
return requestFailed();
} else {
clearAttemptCounter();
throw exc;
}
}
private RequestRetryOutcome requestSucceeded(T value) {
Runnable postRequestAction;
if (previousRequestFailed()) {
postRequestAction = IncreasingTimeoutsRequestRetryStrategy.this::onReconnect;
} else {
postRequestAction = null;
}
clearAttemptCounter();
return new RequestRetryOutcome<>(true, value, postRequestAction);
}
private RequestRetryOutcome requestFailed() {
return new RequestRetryOutcome<>(false, null, this::sleep);
}
private void onReconnect() {
System.out.println("Connection restored!");
}
private void sleep() {
try {
long maxSleepTime = Math.min(powerOf2(attemptCounter - 1), retryTimeoutCap);
long sleepTime = ThreadLocalRandom.current().nextLong(0, maxSleepTime + 1);
logger.debug("Attempt #%d to make a request failed. Next try in %d ms.", attemptCounter, sleepTime);
Thread.sleep(sleepTime);
} catch (InterruptedException ignored) {
logger.debug("Sleep in request retry loop was interrupted!");
}
}
private boolean previousRequestFailed() {
return attemptCounter > 1;
}
private void incrementAttemptCounter() {
attemptCounter++;
}
private void clearAttemptCounter() {
attemptCounter = 0;
}
private static long powerOf2(int exponent) {
return 1L << exponent;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy