diff --git a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java index 25556a74..4747a457 100644 --- a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java @@ -43,6 +43,7 @@ * @author Artem Bilan * @author Marius Lichtblau * @author Anton Aharkau + * @author Kim Sumin */ @SuppressWarnings("serial") public class ExponentialBackOffPolicy implements SleepingBackOffPolicy { @@ -130,6 +131,9 @@ protected void cloneValues(ExponentialBackOffPolicy target) { * @param initialInterval the initial interval */ public void setInitialInterval(long initialInterval) { + if (initialInterval < 1) { + logger.warn("Initial interval must be at least 1, but was " + initialInterval); + } this.initialInterval = initialInterval > 1 ? initialInterval : 1; } @@ -139,6 +143,9 @@ public void setInitialInterval(long initialInterval) { * @param multiplier the multiplier */ public void setMultiplier(double multiplier) { + if (multiplier <= 1.0) { + logger.warn("Multiplier must be > 1.0 for effective exponential backoff, but was " + multiplier); + } this.multiplier = multiplier > 1.0 ? multiplier : 1.0; } @@ -150,6 +157,9 @@ public void setMultiplier(double multiplier) { * @param maxInterval in milliseconds. */ public void setMaxInterval(long maxInterval) { + if (maxInterval < 1) { + logger.warn("Max interval must be positive, but was " + maxInterval); + } this.maxInterval = maxInterval > 0 ? maxInterval : 1; } diff --git a/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java b/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java index 3182c14a..fe93d77d 100644 --- a/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java +++ b/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java @@ -16,10 +16,15 @@ package org.springframework.retry.backoff; +import org.apache.commons.logging.Log; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.beans.DirectFieldAccessor; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; /** * @author Rob Harrop @@ -27,6 +32,7 @@ * @author Gary Russell * @author Marius Lichtblau * @author Anton Aharkau + * @author Kim Sumin */ public class ExponentialBackOffPolicyTests { @@ -125,4 +131,50 @@ public void sleep(long backOffPeriod) throws InterruptedException { assertThat(Thread.interrupted()).isTrue(); } + @Test + public void testSetMultiplierWithWarning() { + Log logMock = mock(Log.class); + ExponentialBackOffPolicy strategy = new ExponentialBackOffPolicy(); + + DirectFieldAccessor accessor = new DirectFieldAccessor(strategy); + accessor.setPropertyValue("logger", logMock); + + strategy.setMultiplier(1.0); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(logMock).warn(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("Multiplier must be > 1.0 for effective exponential backoff, but was 1.0"); + } + + @Test + public void testSetInitialIntervalWithWarning() { + Log logMock = mock(Log.class); + ExponentialBackOffPolicy strategy = new ExponentialBackOffPolicy(); + + DirectFieldAccessor accessor = new DirectFieldAccessor(strategy); + accessor.setPropertyValue("logger", logMock); + + strategy.setInitialInterval(0); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(logMock).warn(captor.capture()); + assertThat(captor.getValue()).isEqualTo("Initial interval must be at least 1, but was 0"); + } + + @Test + public void testSetMaxIntervalWithWarning() { + Log logMock = mock(Log.class); + ExponentialBackOffPolicy strategy = new ExponentialBackOffPolicy(); + + DirectFieldAccessor accessor = new DirectFieldAccessor(strategy); + accessor.setPropertyValue("logger", logMock); + + strategy.setMaxInterval(0); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(logMock).warn(captor.capture()); + assertThat(captor.getValue()).isEqualTo("Max interval must be positive, but was 0"); + } + }