Skip to content

Commit 1786eb2

Browse files
committed
Introduce RetryInterruptedException to address off-by-one error
Prior to this commit, a RetryException thrown for an InterruptedException returned the wrong value from getRetryCount(). Specifically, the count was one more than it should have been, since the suppressed exception list contains the initial exception as well as all retry attempt exceptions. To address that, this commit introduces an internal RetryInterruptedException which accounts for this off-by-one error. Closes gh-35434
1 parent b2cdfba commit 1786eb2

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

spring-core/src/main/java/org/springframework/core/retry/RetryTemplate.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public RetryListener getRetryListener() {
164164
}
165165
catch (InterruptedException interruptedException) {
166166
Thread.currentThread().interrupt();
167-
RetryException retryException = new RetryException(
167+
RetryException retryException = new RetryInterruptedException(
168168
"Unable to back off for retryable operation '%s'".formatted(retryableName),
169169
interruptedException);
170170
exceptions.forEach(retryException::addSuppressed);
@@ -200,4 +200,20 @@ public RetryListener getRetryListener() {
200200
}
201201
}
202202

203+
private static class RetryInterruptedException extends RetryException {
204+
205+
private static final long serialVersionUID = 1L;
206+
207+
208+
RetryInterruptedException(String message, InterruptedException cause) {
209+
super(message, cause);
210+
}
211+
212+
@Override
213+
public int getRetryCount() {
214+
return (getSuppressed().length - 1);
215+
}
216+
217+
}
218+
203219
}

spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,7 @@ void retryWithInterruptionDuringSleep() {
238238
.withMessageMatching("Unable to back off for retryable operation '.+?'")
239239
.withCause(interruptedException)
240240
.satisfies(throwable -> assertThat(throwable.getSuppressed()).containsExactly(exception))
241-
// TODO Fix retry count for InterruptedException scenario.
242-
// Retry count should actually be 0.
243-
.satisfies(throwable -> assertThat(throwable.getRetryCount()).isEqualTo(1))
241+
.satisfies(throwable -> assertThat(throwable.getRetryCount()).isZero())
244242
.satisfies(throwable -> inOrder.verify(retryListener).onRetryPolicyInterruption(retryPolicy, retryable, throwable));
245243

246244
verifyNoMoreInteractions(retryListener);

0 commit comments

Comments
 (0)