LimitRetryAfter.java
package com.maybeitssquid.retry;
import jakarta.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* Predicate to prevent a retry if there is a {@code Retry-After} header that specifies too long a
* wait interval.
*/
public class LimitRetryAfter implements Predicate<HttpServletResponse> {
/** The parser to read Retry-After headers from the response. */
private final Function<HttpServletResponse, Optional<Duration>> parser;
/** The maximum wait interval */
private final Duration maximum;
/**
* Creates a predicate to limit intervals requested by an HTTP Retry-After header.
*
* @param maximum the maximum wait interval
* @param parser the parser for the headers
*/
public LimitRetryAfter(
final Duration maximum, final Function<HttpServletResponse, Optional<Duration>> parser) {
this.parser = parser;
this.maximum = maximum;
}
/**
* Creates a predicate to limit intervals requested by an HTTP Retry-After header, using an
* extended parser.
*
* @param limit the maximum wait interval
* @return a limiter predicate
* @see RetryAfterParser#extended()
*/
public static LimitRetryAfter maximum(final Duration limit) {
return new LimitRetryAfter(limit, RetryAfterParser.extended());
}
/**
* Convenience wrapper to express the limit in milliseconds.
*
* @param milliseconds the limit in milliseconds
* @return a limiter predicate
* @see #maximum(Duration)
*/
public static LimitRetryAfter maximum(final long milliseconds) {
return maximum(Duration.ofMillis(milliseconds));
}
/**
* Gets the maximum wait interval allowed
*
* @return the maximum wait interval allowed
*/
public Duration getMaximum() {
return this.maximum;
}
/**
* Tests whether there is a Retry-After header that would exceed the limit.
*
* @param t the HTTP response to check for a Retry-After header
* @return false if there is a Retry-After header and the requested duration would exceed the
* limit
*/
@Override
public boolean test(final HttpServletResponse t) {
return this.parser.apply(t).map(ra -> ra.compareTo(getMaximum()) < 1).orElse(true);
}
}