Accept zero for RetryPolicy.Builder.delay()

This aligns the programmatic RetryPolicy configuration option with the
delay support in @⁠Retryable.

See gh-35110
This commit is contained in:
Sam Brannen
2025-07-01 17:40:15 +02:00
parent c9078bfe14
commit cc31bf3c33
5 changed files with 25 additions and 25 deletions
@@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.springframework.core.retry.RetryPolicy.Builder.DEFAULT_DELAY;
import static org.springframework.util.backoff.BackOffExecution.STOP;
/**
@@ -38,14 +39,14 @@ class MaxAttemptsRetryPolicyTests {
@Test
void maxAttempts() {
var retryPolicy = RetryPolicy.builder().maxAttempts(2).delay(Duration.ofMillis(1)).build();
var retryPolicy = RetryPolicy.builder().maxAttempts(2).delay(Duration.ofMillis(0)).build();
var backOffExecution = retryPolicy.getBackOff().start();
var throwable = mock(Throwable.class);
assertThat(retryPolicy.shouldRetry(throwable)).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isZero();
assertThat(retryPolicy.shouldRetry(throwable)).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isZero();
assertThat(retryPolicy.shouldRetry(throwable)).isTrue();
assertThat(backOffExecution.nextBackOff()).isEqualTo(STOP);
@@ -65,13 +66,13 @@ class MaxAttemptsRetryPolicyTests {
// 4 retries
assertThat(retryPolicy.shouldRetry(new NumberFormatException())).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(1);
assertThat(retryPolicy.shouldRetry(new IllegalStateException())).isFalse();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(1);
assertThat(retryPolicy.shouldRetry(new IllegalStateException())).isFalse();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(1);
assertThat(retryPolicy.shouldRetry(new CustomNumberFormatException())).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(1);
// After policy exhaustion
assertThat(retryPolicy.shouldRetry(new NumberFormatException())).isTrue();
@@ -92,17 +93,17 @@ class MaxAttemptsRetryPolicyTests {
// 6 retries
assertThat(retryPolicy.shouldRetry(new IOException())).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
assertThat(retryPolicy.shouldRetry(new RuntimeException())).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
assertThat(retryPolicy.shouldRetry(new FileNotFoundException())).isFalse();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
assertThat(retryPolicy.shouldRetry(new FileSystemException("file"))).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
assertThat(retryPolicy.shouldRetry(new CustomFileSystemException("file"))).isFalse();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
assertThat(retryPolicy.shouldRetry(new IOException())).isTrue();
assertThat(backOffExecution.nextBackOff()).isGreaterThan(0);
assertThat(backOffExecution.nextBackOff()).isEqualTo(DEFAULT_DELAY);
// After policy exhaustion
assertThat(retryPolicy.shouldRetry(new IOException())).isTrue();
@@ -162,12 +162,9 @@ class RetryPolicyTests {
@Test
void delayPreconditions() {
assertThatIllegalArgumentException()
.isThrownBy(() -> RetryPolicy.builder().delay(Duration.ofMillis(0)))
.withMessage("Invalid duration (0ms): delay must be positive.");
assertThatIllegalArgumentException()
.isThrownBy(() -> RetryPolicy.builder().delay(Duration.ofMillis(-1)))
.withMessage("Invalid duration (-1ms): delay must be positive.");
.withMessage("Invalid delay (-1ms): must be >= 0.");
}
@Test
@@ -51,7 +51,7 @@ class RetryTemplateTests {
void configureRetryTemplate() {
var retryPolicy = RetryPolicy.builder()
.maxAttempts(3)
.delay(Duration.ofMillis(1))
.delay(Duration.ofMillis(0))
.build();
retryTemplate.setRetryPolicy(retryPolicy);
@@ -171,7 +171,7 @@ class RetryTemplateTests {
var retryPolicy = RetryPolicy.builder()
.maxAttempts(Integer.MAX_VALUE)
.delay(Duration.ofMillis(1))
.delay(Duration.ofMillis(0))
.includes(IOException.class)
.build();
@@ -194,13 +194,13 @@ class RetryTemplateTests {
argumentSet("Excludes",
RetryPolicy.builder()
.maxAttempts(Integer.MAX_VALUE)
.delay(Duration.ofMillis(1))
.delay(Duration.ofMillis(0))
.excludes(FileNotFoundException.class)
.build()),
argumentSet("Includes & Excludes",
RetryPolicy.builder()
.maxAttempts(Integer.MAX_VALUE)
.delay(Duration.ofMillis(1))
.delay(Duration.ofMillis(0))
.includes(IOException.class)
.excludes(FileNotFoundException.class)
.build())