diff --git a/spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java b/spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java index 2747703bd6e..fc8b1e1022f 100644 --- a/spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java +++ b/spring-core/src/main/java/org/springframework/util/backoff/ExponentialBackOff.java @@ -311,6 +311,8 @@ public class ExponentialBackOff implements BackOff { long jitter = getJitter(); if (jitter > 0) { long initialInterval = getInitialInterval(); + // When initialInterval is 0 the interval never grows, so the scale factor + // stays at its baseline value of 1 and the full configured jitter is applied. long applicableJitter = jitter * (initialInterval > 0 ? (interval / initialInterval) : 1); long min = Math.max(interval - applicableJitter, initialInterval); long max = Math.min(interval + applicableJitter, getMaxInterval()); diff --git a/spring-core/src/test/java/org/springframework/util/ExponentialBackOffTests.java b/spring-core/src/test/java/org/springframework/util/ExponentialBackOffTests.java index 095ff93d9ed..50999afc589 100644 --- a/spring-core/src/test/java/org/springframework/util/ExponentialBackOffTests.java +++ b/spring-core/src/test/java/org/springframework/util/ExponentialBackOffTests.java @@ -119,17 +119,15 @@ class ExponentialBackOffTests { assertThatIllegalArgumentException().isThrownBy(() -> backOff.setMultiplier(0.9)); } - @Test + @Test // gh-36932 void jitterWithZeroInitialInterval() { - // 'initialInterval = 0' and 'jitter > 0' are both individually accepted - // configurations, so their combination must not throw. With initialInterval - // of 0, the first nextBackOff() previously evaluated 'jitter * (0 / 0)', - // resulting in an integer division by zero. ExponentialBackOff backOff = new ExponentialBackOff(); backOff.setInitialInterval(0); backOff.setJitter(100); - BackOffExecution execution = backOff.start(); + + // 'initialInterval = 0' and 'jitter > 0' are both individually accepted + // configurations, so their combination must not throw. assertThatNoException().isThrownBy(execution::nextBackOff); }