Update RetryPolicySettings to configure exception policy as well
Closes gh-47264
This commit is contained in:
parent
cb51a44e2b
commit
da8eac3483
|
@ -17,7 +17,10 @@
|
|||
package org.springframework.boot.retry;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
|
@ -53,6 +56,12 @@ public final class RetryPolicySettings {
|
|||
*/
|
||||
public static final Duration DEFAULT_MAX_DELAY = Duration.ofMillis(RetryPolicy.Builder.DEFAULT_MAX_DELAY);
|
||||
|
||||
private List<Class<? extends Throwable>> exceptionIncludes = new ArrayList<>();
|
||||
|
||||
private List<Class<? extends Throwable>> exceptionExcludes = new ArrayList<>();
|
||||
|
||||
private @Nullable Predicate<Throwable> exceptionPredicate;
|
||||
|
||||
private Long maxAttempts = DEFAULT_MAX_ATTEMPTS;
|
||||
|
||||
private Duration delay = DEFAULT_DELAY;
|
||||
|
@ -72,6 +81,9 @@ public final class RetryPolicySettings {
|
|||
public RetryPolicy createRetryPolicy() {
|
||||
PropertyMapper map = PropertyMapper.get();
|
||||
RetryPolicy.Builder builder = RetryPolicy.builder();
|
||||
map.from(this::getExceptionIncludes).to(builder::includes);
|
||||
map.from(this::getExceptionExcludes).to(builder::excludes);
|
||||
map.from(this::getExceptionPredicate).to(builder::predicate);
|
||||
map.from(this::getMaxAttempts).to(builder::maxAttempts);
|
||||
map.from(this::getDelay).to(builder::delay);
|
||||
map.from(this::getJitter).to(builder::jitter);
|
||||
|
@ -80,6 +92,64 @@ public final class RetryPolicySettings {
|
|||
return (this.factory != null) ? this.factory.apply(builder) : builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the applicable exception types to attempt a retry for.
|
||||
* <p>
|
||||
* The default is empty, leading to a retry attempt for any exception.
|
||||
* @return the applicable exception types
|
||||
*/
|
||||
public List<Class<? extends Throwable>> getExceptionIncludes() {
|
||||
return this.exceptionIncludes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the applicable exception types to attempt a retry for by the given
|
||||
* {@code includes}. Alternatively consider using {@link #getExceptionIncludes()} to
|
||||
* mutate the existing list.
|
||||
* @param includes the applicable exception types
|
||||
*/
|
||||
public void setExceptionIncludes(List<Class<? extends Throwable>> includes) {
|
||||
this.exceptionIncludes = new ArrayList<>(includes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the non-applicable exception types to avoid a retry for.
|
||||
* <p>
|
||||
* The default is empty, leading to a retry attempt for any exception.
|
||||
* @return the non-applicable exception types
|
||||
*/
|
||||
public List<Class<? extends Throwable>> getExceptionExcludes() {
|
||||
return this.exceptionExcludes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the non-applicable exception types to attempt a retry for by the given
|
||||
* {@code excludes}. Alternatively consider using {@link #getExceptionExcludes()} to
|
||||
* mutate the existing list.
|
||||
* @param excludes the non-applicable types
|
||||
*/
|
||||
public void setExceptionExcludes(List<Class<? extends Throwable>> excludes) {
|
||||
this.exceptionExcludes = new ArrayList<>(excludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the predicate to use to determine whether to retry a failed operation based
|
||||
* on a given {@link Throwable}.
|
||||
* @return the predicate to use
|
||||
*/
|
||||
public @Nullable Predicate<Throwable> getExceptionPredicate() {
|
||||
return this.exceptionPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the predicate to use to determine whether to retry a failed operation based on
|
||||
* a given {@link Throwable}.
|
||||
* @param exceptionPredicate the predicate to use
|
||||
*/
|
||||
public void setExceptionPredicate(@Nullable Predicate<Throwable> exceptionPredicate) {
|
||||
this.exceptionPredicate = exceptionPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of retry attempts.
|
||||
* @return the maximum number of retry attempts
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
package org.springframework.boot.retry;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -25,6 +28,8 @@ import org.springframework.util.backoff.BackOff;
|
|||
import org.springframework.util.backoff.ExponentialBackOff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
|
@ -34,6 +39,78 @@ import static org.mockito.Mockito.mock;
|
|||
*/
|
||||
class RetryPolicySettingsTests {
|
||||
|
||||
@Test
|
||||
void exceptionIncludesCanBeReplaced() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
settings.getExceptionIncludes().add(IllegalStateException.class);
|
||||
settings.setExceptionIncludes(List.of(IllegalArgumentException.class));
|
||||
assertThat(settings.getExceptionIncludes()).containsExactly(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void exceptionIncludesListIsCopied() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
List<Class<? extends Throwable>> includes = new ArrayList<>();
|
||||
includes.add(IllegalStateException.class);
|
||||
settings.setExceptionIncludes(includes);
|
||||
includes.add(IllegalArgumentException.class);
|
||||
assertThat(settings.getExceptionIncludes()).containsExactly(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRetryPolicyWithExceptionIncludes() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
settings.getExceptionIncludes().add(IllegalStateException.class);
|
||||
RetryPolicy retryPolicy = settings.createRetryPolicy();
|
||||
assertThat(retryPolicy.shouldRetry(new IllegalStateException("test"))).isTrue();
|
||||
assertThat(retryPolicy.shouldRetry(new IllegalArgumentException("test"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void exceptionExcludesCanBeReplaced() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
settings.getExceptionExcludes().add(IllegalStateException.class);
|
||||
settings.setExceptionExcludes(List.of(IllegalArgumentException.class));
|
||||
assertThat(settings.getExceptionExcludes()).containsExactly(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void exceptionExcludesListIsCopied() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
List<Class<? extends Throwable>> excludes = new ArrayList<>();
|
||||
excludes.add(IllegalStateException.class);
|
||||
settings.setExceptionExcludes(excludes);
|
||||
excludes.add(IllegalArgumentException.class);
|
||||
assertThat(settings.getExceptionExcludes()).containsExactly(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRetryPolicyWithExceptionExcludes() {
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
settings.getExceptionExcludes().add(IllegalStateException.class);
|
||||
RetryPolicy retryPolicy = settings.createRetryPolicy();
|
||||
assertThat(retryPolicy.shouldRetry(new IllegalStateException("test"))).isFalse();
|
||||
assertThat(retryPolicy.shouldRetry(new IllegalArgumentException("test"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getDefaultExceptionPredicate() {
|
||||
assertThat(new RetryPolicySettings().getExceptionPredicate()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRetryPolicyWithExceptionPredicate() {
|
||||
IllegalArgumentException exception = new IllegalArgumentException("test");
|
||||
Predicate<Throwable> exceptionPredicate = mock();
|
||||
given(exceptionPredicate.test(exception)).willReturn(true);
|
||||
RetryPolicySettings settings = new RetryPolicySettings();
|
||||
settings.setExceptionPredicate(exceptionPredicate);
|
||||
RetryPolicy retryPolicy = settings.createRetryPolicy();
|
||||
assertThat(retryPolicy.shouldRetry(exception)).isTrue();
|
||||
then(exceptionPredicate).should().test(exception);
|
||||
then(exceptionPredicate).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createRetryPolicyWithDefaultsMatchesBackOffDefaults() {
|
||||
RetryPolicy defaultRetryPolicy = RetryPolicy.builder().build();
|
||||
|
|
Loading…
Reference in New Issue