I am trying to create a utility class in pure Java that will contain the logic needed for the Exponential Backoff Algorithm implementation with full jitter as there will be multiple clients sending requests. I have another class with a method that executes a GET or a POST request and returns a response with a status code. I want to retry (aka use the exponential backoff strategy) only if the status code is in the 5xx. Current code is not compiling.
The calling method looks like this:
HttpResponse response = executeGetRequest( params );
int statusCode = response.getStatusCode();
//some status code validation
My ExponentialBackoffStrategy class is:
public class ExponentialBackoffStrategy {
private final long maxBackoff;
private long backoffValue;
private long attempts;
private static final long DEFAULT_MAX_RETRIES = 900_000;
private Random random = new Random();
public ExponentialBackoffStrategy( long maxBackoff ) {
this.maxBackoff = maxBackoff;
}
public long getWaitTimeExp() {
if( backoffValue >= maxBackoff ) {
return maxBackoff;
}
double pow = Math.pow( 2, attempts++ );
int rand = random.nextInt( 1000 );
backoffValue = ( long ) Math.min( pow + rand, maxBackoff );
return backoffValue;
}
public static ExponentialBackoffStrategy getDefault() {
return new ExponentialBackoffStrategy( DEFAULT_MAX_RETRIES );
}
}
I want to get some feedback on the implemented class in regards to if I can do anything better and also how to integrate it with the caller method. My idea as of right now is:
ExponentialBackoffStrategy backoff = ExponentialBackoffStrategy.getDefault();
boolean retry = false;
HttpResponse response = null;
int statusCode = 0;
do {
response = executeGetRequest( params );
statusCode = response.getStatusLine().getStatusCode();
if( statusCode >= 500 && statusCode < 600 ) {
retry = true;
try {
Thread.sleep( backoff.getWaitTimeExp() );
} catch ( InterruptedException e ) {
//handle exception
}
}
} while ( retry );
Any help would be greatly appreciated!
EDIT: The response is actually located in try with resources.
try ( HttpResponse response = backoff.attempt(
() -> executeGetRequest( params ),
r -> {
final int statusCode = response.getStatusLine().getStatusCode();
return statusCode < 500 || statusCode >= 600;
}
);)
I am running into two issues:
- On the line
final int statusCode = response.getStatusLine().getStatusCode();
"response" is underlined red "variable 'response' may not have been initialized". Tried to take it outside the try block and try with resources doesn't like it. - executeGetRequest now needs a catch block inside of the lambda:
try ( HttpResponse response = executePostRequest( params ) ) {