|
18 | 18 | import static org.assertj.core.api.Assertions.assertThat; |
19 | 19 |
|
20 | 20 | import java.time.Duration; |
| 21 | +import java.util.function.Supplier; |
21 | 22 | import org.junit.jupiter.api.Test; |
22 | 23 | import software.amazon.awssdk.retries.api.AcquireInitialTokenResponse; |
23 | 24 | import software.amazon.awssdk.retries.api.BackoffStrategy; |
@@ -82,24 +83,33 @@ void v20_throttlingRetry_deducts5Tokens() { |
82 | 83 |
|
83 | 84 | @Test |
84 | 85 | void v21Enabled_backoffUses50msBaseDelay() { |
85 | | - RetryStrategy strategy = StandardRetryStrategy.builder(true) |
86 | | - .retryOnException(t -> true) |
87 | | - .build(); |
88 | 86 |
|
89 | | - RefreshRetryTokenResponse response = refreshToken(strategy, new RuntimeException("err")); |
90 | | - // First retry delay should be in [0, 50ms] (jittered) |
91 | | - assertThat(response.delay()).isBetween(Duration.ZERO, Duration.ofMillis(50)); |
| 87 | + Supplier<RetryStrategy> stratSupplier = () -> StandardRetryStrategy.builder(true) |
| 88 | + .retryOnException(t -> true) |
| 89 | + .build(); |
| 90 | + |
| 91 | + probabilisticAssertDelayBetween(stratSupplier, new RuntimeException("err"), Duration.ZERO, Duration.ofMillis(50)); |
| 92 | + } |
| 93 | + |
| 94 | + @Test |
| 95 | + void v21Enabled_throttlingBackoffUses1000msBaseDelay() { |
| 96 | + |
| 97 | + Supplier<RetryStrategy> stratSupplier = () -> StandardRetryStrategy.builder(true) |
| 98 | + .retryOnException(t -> true) |
| 99 | + .treatAsThrottling(t -> true) |
| 100 | + .build(); |
| 101 | + |
| 102 | + probabilisticAssertDelayBetween(stratSupplier, new RuntimeException("err"), Duration.ZERO, Duration.ofMillis(1000)); |
92 | 103 | } |
93 | 104 |
|
94 | 105 | @Test |
95 | 106 | void v20_backoffUses100msBaseDelay() { |
96 | | - RetryStrategy strategy = StandardRetryStrategy.builder(false) |
97 | | - .retryOnException(t -> true) |
98 | | - .build(); |
| 107 | + Supplier<RetryStrategy> stratSupplier = () -> StandardRetryStrategy.builder(false) |
| 108 | + .retryOnException(t -> true) |
| 109 | + .build(); |
| 110 | + |
| 111 | + probabilisticAssertDelayBetween(stratSupplier, new RuntimeException("err"), Duration.ZERO, Duration.ofMillis(100)); |
99 | 112 |
|
100 | | - RefreshRetryTokenResponse response = refreshToken(strategy, new RuntimeException("err")); |
101 | | - // First retry delay should be in [0, 100ms] (jittered) |
102 | | - assertThat(response.delay()).isBetween(Duration.ZERO, Duration.ofMillis(100)); |
103 | 113 | } |
104 | 114 |
|
105 | 115 | @Test |
@@ -135,4 +145,15 @@ private RefreshRetryTokenResponse refreshToken(RetryStrategy strategy, Exception |
135 | 145 | return strategy.refreshRetryToken( |
136 | 146 | RefreshRetryTokenRequest.builder().token(initial.token()).failure(failure).build()); |
137 | 147 | } |
| 148 | + |
| 149 | + // Backoffs are jittered, so verify it by testing it many times |
| 150 | + private void probabilisticAssertDelayBetween(Supplier<RetryStrategy> strategy, |
| 151 | + Exception failure, |
| 152 | + Duration min, |
| 153 | + Duration max) { |
| 154 | + for (int i = 0; i < 128; ++i) { |
| 155 | + RefreshRetryTokenResponse response = refreshToken(strategy.get(), failure); |
| 156 | + assertThat(response.delay()).isBetween(min, max); |
| 157 | + } |
| 158 | + } |
138 | 159 | } |
0 commit comments