
io.sphere.sdk.retry.RetryAction Maven / Gradle / Ivy
The newest version!
package io.sphere.sdk.retry;
import javax.annotation.Nullable;
import java.time.Duration;
import java.util.function.Function;
import static io.sphere.sdk.retry.RetryActions.validateMaxAttempts;
/**
* Provides some default implementations for {@link RetryRule#apply(RetryContext)}.
*/
@FunctionalInterface
public interface RetryAction extends Function {
@Nullable
RetryStrategy apply(final RetryContext retryContext);
/**
* Retry in the future with a fixed waiting time.
*
* @param maxAttempts maximum amount of attempts until giving up and throwing the latest Exception
* @param duration time to wait before retrying
* @return action
*/
static RetryAction ofScheduledRetry(final long maxAttempts, final Duration duration) {
return ofScheduledRetry(maxAttempts, c -> duration);
}
/**
* Retry in the future with a waiting time depending on the {@link RetryContext}, for example to take the number of
* attempts in consideration.
*
* {@include.example io.sphere.sdk.client.retry.RetryBadGatewayExample}
*
* @param maxAttempts maximum amount of attempts until giving up and throwing the latest Exception
* @param durationFunction function that takes the {@link RetryContext} and provides the duration to wait until the next retry
* @return action
*/
static RetryAction ofScheduledRetry(final long maxAttempts, final Function durationFunction) {
validateMaxAttempts(maxAttempts);
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
if (retryOperationContext.getAttempt() > maxAttempts) {
return RetryStrategy.resume(retryOperationContext.getLatestError());
} else {
try {
final Duration duration = durationFunction.apply(retryOperationContext);
final Object parameterObject = retryOperationContext.getLatestParameter();
return RetryStrategy.retryScheduled(parameterObject, duration);
} catch (Throwable e) {
return RetryStrategy.resume(e);
}
}
}
@Override
protected String getDescription() {
return "schedule retry up to " + maxAttempts + " times";
}
};
}
static RetryAction ofShutdownServiceAndSendFirstException() {
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
return RetryStrategy.stop(retryOperationContext.getFirstError());
}
@Override
protected String getDescription() {
return "shut down and send first exception";
}
};
}
static RetryAction ofShutdownServiceAndSendLatestException() {
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
return RetryStrategy.stop(retryOperationContext.getLatestError());
}
@Override
protected String getDescription() {
return "shut down and send latest exception";
}
};
}
static RetryAction ofGiveUpAndSendFirstException() {
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
return RetryStrategy.resume(retryOperationContext.getFirstError());
}
@Override
protected String getDescription() {
return "shut down and send first exception";
}
};
}
/**
* Throws the latest error and does not retry.
*
* @return action
*/
static RetryAction ofGiveUpAndSendLatestException() {
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
return RetryStrategy.resume(retryOperationContext.getLatestError());
}
@Override
protected String getDescription() {
return "shut down and send latest exception";
}
};
}
/**
* Retries immediately for a maximum amount of attempts.
*
* @param maxAttempts maximum amount of attempts until giving up and throwing the latest Exception
* @return action
*/
static RetryAction ofImmediateRetries(final long maxAttempts) {
validateMaxAttempts(maxAttempts);
return new RetryActionImpl() {
@Override
public RetryStrategy apply(final RetryContext retryOperationContext) {
if (retryOperationContext.getAttempt() > maxAttempts) {
return RetryStrategy.resume(retryOperationContext.getLatestError());
} else {
final Object parameterObject = retryOperationContext.getLatestParameter();
return RetryStrategy.retryImmediately(parameterObject);
}
}
@Override
protected String getDescription() {
return "immediate retry up to " + maxAttempts + " times";
}
};
}
/**
* Retry in the future with exponential backoff strategy.
* @param maxAttempts maximum amount of attempts until giving up and throwing the latest Exception
* @param initialRetryDelay initial time to wait before retrying in milliseconds
* @param maxDelay maximum time to wait before retrying in milliseconds
* @return action
*/
static RetryAction ofExponentialBackoff(final long maxAttempts, final long initialRetryDelay, final long maxDelay) {
return ofScheduledRetry(maxAttempts, c -> calculateDurationWithExponentialRandomBackoff(c.getAttempt(), initialRetryDelay, maxDelay));
}
/**
* Computes a exponential backoff time delay in milliseconds to be used in retries, the delay grows with failed
* retry attempts count with a randomness interval.
* (see: )
* (see: )
*
* @param retryAttempt the number of attempts already tried by the client.
* @param initialRetryDelay the initial Retry delay.
* @param maxDelay the maxDelay in milliseconds.
* @return a duration in milliseconds, that grows with the number of failed attempts.
*/
static Duration calculateDurationWithExponentialRandomBackoff(final long retryAttempt,
final long initialRetryDelay,
final long maxDelay) {
final double exponentialFactor = Math.pow(2, retryAttempt - 1);
final double jitter = 1 + Math.random();
final long delay = (long)Math.min(initialRetryDelay * exponentialFactor * jitter, maxDelay);
return Duration.ofMillis(delay);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy