diff --git a/spring-core/src/main/java/org/springframework/core/retry/RetryTemplate.java b/spring-core/src/main/java/org/springframework/core/retry/RetryTemplate.java index 95b024e8370..c0f5163a45b 100644 --- a/spring-core/src/main/java/org/springframework/core/retry/RetryTemplate.java +++ b/spring-core/src/main/java/org/springframework/core/retry/RetryTemplate.java @@ -213,9 +213,13 @@ public class RetryTemplate implements RetryOperations { // would be if we were to sleep for sleepTime milliseconds. long elapsedTime = System.currentTimeMillis() + sleepTime - startTime; if (elapsedTime >= timeout) { - RetryException retryException = new RetryException( + String message = (sleepTime > 0 ? """ + Retry policy for operation '%s' would exceed timeout (%d ms) due \ + to pending sleep time (%d ms); preemptively aborting execution""" + .formatted(retryable.getName(), timeout, sleepTime) : "Retry policy for operation '%s' exceeded timeout (%d ms); aborting execution" - .formatted(retryable.getName(), timeout), exceptions.removeLast()); + .formatted(retryable.getName(), timeout)); + RetryException retryException = new RetryException(message, exceptions.removeLast()); exceptions.forEach(retryException::addSuppressed); this.retryListener.onRetryPolicyTimeout(this.retryPolicy, retryable, retryException); throw retryException; diff --git a/spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java b/spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java index dd1190afc04..88adcb62478 100644 --- a/spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java +++ b/spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java @@ -502,7 +502,10 @@ class RetryTemplateTests { assertThat(invocationCount).hasValue(0); assertThatExceptionOfType(RetryException.class) .isThrownBy(() -> retryTemplate.execute(retryable)) - .withMessageMatching("Retry policy for operation '.+?' exceeded timeout \\(5 ms\\); aborting execution") + .withMessageMatching(""" + Retry policy for operation '.+?' would exceed timeout \\(5 ms\\) \ + due to pending sleep time \\(10 ms\\); preemptively aborting execution\ + """) .withCause(new CustomException("Boom 1")) .satisfies(throwable -> inOrder.verify(retryListener).onRetryPolicyTimeout( eq(retryPolicy), eq(retryable), eq(throwable)));