diff --git a/framework-docs/modules/ROOT/pages/core/resilience.adoc b/framework-docs/modules/ROOT/pages/core/resilience.adoc index a186c9c81ff..fa68ac4fd43 100644 --- a/framework-docs/modules/ROOT/pages/core/resilience.adoc +++ b/framework-docs/modules/ROOT/pages/core/resilience.adoc @@ -81,6 +81,13 @@ public void sendNotification() { } ---- +[NOTE] +==== +When `delay` is `0` combined with a positive `jitter`, the delay never grows +regardless of any configured `multiplier`, so the full configured `jitter` is +applied directly as a random delay in the range from `0` to `min(jitter, maxDelay)`. +==== + Last but not least, `@Retryable` also works for reactive methods with a reactive return type, decorating the pipeline with Reactor's retry capabilities: @@ -263,6 +270,13 @@ and an exponential back-off strategy with a bit of jitter. () -> jmsClient.destination("notifications").send(...)); ---- +[NOTE] +==== +When `delay` is zero combined with a positive `jitter`, the delay never grows +regardless of any configured `multiplier`, so the full configured `jitter` is +applied directly as a random delay in the range from zero to `min(jitter, maxDelay)`. +==== + [TIP] ==== Although the factory methods and builder API for `RetryPolicy` cover most common diff --git a/spring-context/src/main/java/org/springframework/resilience/annotation/Retryable.java b/spring-context/src/main/java/org/springframework/resilience/annotation/Retryable.java index f86d69d6cc4..9f929febcdb 100644 --- a/spring-context/src/main/java/org/springframework/resilience/annotation/Retryable.java +++ b/spring-context/src/main/java/org/springframework/resilience/annotation/Retryable.java @@ -197,6 +197,10 @@ public @interface Retryable { * and {@code delay + jitter} but never below the base {@link #delay()} or * above {@link #maxDelay()}. If a multiplier is specified, it is applied * to the jitter value as well. + *

When {@link #delay()} is {@code 0} combined with a positive jitter, + * the delay never grows regardless of any configured multiplier, so the + * full configured jitter is applied directly as a random delay in the range + * from {@code 0} to {@code min(jitter, maxDelay)}. *

The time unit is milliseconds by default but can be overridden via * {@link #timeUnit}. *

The default is 0 (no jitter). diff --git a/spring-core/src/main/java/org/springframework/core/retry/RetryPolicy.java b/spring-core/src/main/java/org/springframework/core/retry/RetryPolicy.java index b664c7961f2..374e02dfb47 100644 --- a/spring-core/src/main/java/org/springframework/core/retry/RetryPolicy.java +++ b/spring-core/src/main/java/org/springframework/core/retry/RetryPolicy.java @@ -281,6 +281,11 @@ public interface RetryPolicy { * {@linkplain #maxDelay(Duration) max delay}. *

If a {@linkplain #multiplier(double) multiplier} is specified, it * is applied to the jitter value as well. + *

When the configured {@linkplain #delay(Duration) delay} is zero + * combined with a positive jitter, the delay never grows regardless of + * any configured multiplier, so the full configured jitter is applied + * directly as a random delay in the range from zero to + * {@code min(jitter, maxDelay)}. *

The default is no jitter. *

The supplied value will override any previously configured value. *

You should not specify this configuration option if you have 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 fc8b1e1022f..e60484b8d16 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 @@ -154,6 +154,10 @@ public class ExponentialBackOff implements BackOff { * {@code initialInterval} or above {@code maxInterval}. *

If a {@code multiplier} is specified, it is applied to the jitter value * as well. + *

When {@code initialInterval} is {@code 0} combined with a positive + * jitter, the interval never grows regardless of any configured multiplier, + * so the full configured jitter is applied directly as a random interval in + * the range from {@code 0} to {@code min(jitter, maxInterval)}. * @param jitter the jitter value in milliseconds * @since 7.0 */