Skip to content

Commit 51b6e8c

Browse files
committed
Rename RetryCallback to Retryable
See gh-34716
1 parent f927ff6 commit 51b6e8c

File tree

5 files changed

+56
-50
lines changed

5 files changed

+56
-50
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,23 @@ default void beforeRetry(RetryExecution retryExecution) {
4040
/**
4141
* Called after the first successful retry attempt.
4242
* @param retryExecution the retry execution
43-
* @param result the result of the callback
43+
* @param result the result of the {@link Retryable}
4444
*/
4545
default void onRetrySuccess(RetryExecution retryExecution, Object result) {
4646
}
4747

4848
/**
4949
* Called every time a retry attempt fails.
5050
* @param retryExecution the retry execution
51-
* @param throwable the exception thrown by the callback
51+
* @param throwable the exception thrown by the {@link Retryable}
5252
*/
5353
default void onRetryFailure(RetryExecution retryExecution, Throwable throwable) {
5454
}
5555

5656
/**
5757
* Called if the {@link RetryPolicy} is exhausted.
5858
* @param retryExecution the retry execution
59-
* @param throwable the last exception thrown by the {@link RetryCallback}
59+
* @param throwable the last exception thrown by the {@link Retryable}
6060
*/
6161
default void onRetryPolicyExhaustion(RetryExecution retryExecution, Throwable throwable) {
6262
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@
3131
public interface RetryOperations {
3232

3333
/**
34-
* Execute the given callback (according to the {@link RetryPolicy} configured
35-
* at the implementation level) until it succeeds, or eventually throw an
36-
* exception if the {@code RetryPolicy} is exhausted.
37-
* @param retryCallback the callback to call initially and retry if needed
34+
* Execute the given {@link Retryable} (according to the {@link RetryPolicy}
35+
* configured at the implementation level) until it succeeds, or eventually
36+
* throw an exception if the {@code RetryPolicy} is exhausted.
37+
* @param retryable the {@code Retryable} to execute and retry if needed
3838
* @param <R> the type of the result
39-
* @return the result of the callback, if any
39+
* @return the result of the {@code Retryable}, if any
4040
* @throws RetryException if the {@code RetryPolicy} is exhausted; exceptions
4141
* encountered during retry attempts should be made available as suppressed
4242
* exceptions
4343
*/
44-
<R extends @Nullable Object> R execute(RetryCallback<R> retryCallback) throws RetryException;
44+
<R extends @Nullable Object> R execute(Retryable<R> retryable) throws RetryException;
4545

4646
}

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

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232

3333
/**
3434
* A basic implementation of {@link RetryOperations} that invokes and potentially
35-
* retries a {@link RetryCallback} based on a configured {@link RetryPolicy} and
36-
* {@link BackOff} policy.
35+
* retries a {@link Retryable} operation based on a configured {@link RetryPolicy}
36+
* and {@link BackOff} policy.
3737
*
38-
* <p>By default, a callback will be invoked at most 3 times with a fixed backoff
39-
* of 1 second.
38+
* <p>By default, a retryable operation will be invoked at most 3 times with a
39+
* fixed backoff of 1 second.
4040
*
4141
* <p>A {@link RetryListener} can be {@linkplain #setRetryListener(RetryListener)
4242
* registered} to intercept and inject behavior during key retry phases (before a
@@ -52,7 +52,7 @@
5252
* @see RetryPolicy
5353
* @see BackOff
5454
* @see RetryListener
55-
* @see RetryCallback
55+
* @see Retryable
5656
*/
5757
public class RetryTemplate implements RetryOperations {
5858

@@ -128,55 +128,58 @@ public void setRetryListener(RetryListener retryListener) {
128128
}
129129

130130
/**
131-
* Execute the supplied {@link RetryCallback} according to the configured
132-
* retry and backoff policies.
133-
* <p>If the callback succeeds, its result will be returned. Otherwise, a
134-
* {@link RetryException} will be thrown to the caller.
135-
* @param retryCallback the callback to call initially and retry if needed
131+
* Execute the supplied {@link Retryable} according to the configured retry
132+
* and backoff policies.
133+
* <p>If the {@code Retryable} succeeds, its result will be returned. Otherwise,
134+
* a {@link RetryException} will be thrown to the caller.
135+
* @param retryable the {@code Retryable} to execute and retry if needed
136136
* @param <R> the type of the result
137-
* @return the result of the callback, if any
137+
* @return the result of the {@code Retryable}, if any
138138
* @throws RetryException if the {@code RetryPolicy} is exhausted; exceptions
139139
* encountered during retry attempts are available as suppressed exceptions
140140
*/
141141
@Override
142-
public <R extends @Nullable Object> R execute(RetryCallback<R> retryCallback) throws RetryException {
143-
String callbackName = retryCallback.getName();
142+
public <R extends @Nullable Object> R execute(Retryable<R> retryable) throws RetryException {
143+
String retryableName = retryable.getName();
144144
// Initial attempt
145145
try {
146-
logger.debug(() -> "Preparing to execute callback '" + callbackName + "'");
147-
R result = retryCallback.run();
148-
logger.debug(() -> "Callback '" + callbackName + "' completed successfully");
146+
logger.debug(() -> "Preparing to execute retryable operation '%s'".formatted(retryableName));
147+
R result = retryable.run();
148+
logger.debug(() -> "Retryable operation '%s' completed successfully".formatted(retryableName));
149149
return result;
150150
}
151151
catch (Throwable initialException) {
152152
logger.debug(initialException,
153-
() -> "Execution of callback '" + callbackName + "' failed; initiating the retry process");
153+
() -> "Execution of retryable operation '%s' failed; initiating the retry process"
154+
.formatted(retryableName));
154155
// Retry process starts here
155156
RetryExecution retryExecution = this.retryPolicy.start();
156157
BackOffExecution backOffExecution = this.backOffPolicy.start();
157158
List<Throwable> suppressedExceptions = new ArrayList<>();
158159

159160
Throwable retryException = initialException;
160161
while (retryExecution.shouldRetry(retryException)) {
161-
logger.debug(() -> "Preparing to retry callback '" + callbackName + "'");
162+
logger.debug(() -> "Preparing to retry operation '%s'".formatted(retryableName));
162163
try {
163164
this.retryListener.beforeRetry(retryExecution);
164-
R result = retryCallback.run();
165+
R result = retryable.run();
165166
this.retryListener.onRetrySuccess(retryExecution, result);
166-
logger.debug(() -> "Callback '" + callbackName + "' completed successfully after retry");
167+
logger.debug(() -> "Retryable operation '%s' completed successfully after retry"
168+
.formatted(retryableName));
167169
return result;
168170
}
169171
catch (Throwable currentAttemptException) {
170172
this.retryListener.onRetryFailure(retryExecution, currentAttemptException);
171173
try {
172174
long duration = backOffExecution.nextBackOff();
173-
logger.debug(() -> "Retry callback '" + callbackName + "' failed due to '" +
174-
currentAttemptException.getMessage() + "'; backing off for " + duration + "ms");
175+
logger.debug(() -> "Retryable operation '%s' failed due to '%s'; backing off for %dms"
176+
.formatted(retryableName, currentAttemptException.getMessage(), duration));
175177
Thread.sleep(duration);
176178
}
177179
catch (InterruptedException interruptedException) {
178180
Thread.currentThread().interrupt();
179-
throw new RetryException("Unable to back off for retry callback '" + callbackName + "'",
181+
throw new RetryException(
182+
"Unable to back off for retryable operation '%s'".formatted(retryableName),
180183
interruptedException);
181184
}
182185
suppressedExceptions.add(currentAttemptException);
@@ -185,8 +188,9 @@ public void setRetryListener(RetryListener retryListener) {
185188
}
186189
// The RetryPolicy has exhausted at this point, so we throw a RetryException with the
187190
// initial exception as the cause and remaining exceptions as suppressed exceptions.
188-
RetryException finalException = new RetryException("Retry policy for callback '" + callbackName +
189-
"' exhausted; aborting execution", initialException);
191+
RetryException finalException = new RetryException(
192+
"Retry policy for operation '%s' exhausted; aborting execution".formatted(retryableName),
193+
initialException);
190194
suppressedExceptions.forEach(finalException::addSuppressed);
191195
this.retryListener.onRetryPolicyExhaustion(retryExecution, finalException);
192196
throw finalException;

spring-core/src/main/java/org/springframework/core/retry/RetryCallback.java renamed to spring-core/src/main/java/org/springframework/core/retry/Retryable.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,32 @@
1717
package org.springframework.core.retry;
1818

1919
/**
20-
* Callback interface for a retryable block of code.
20+
* {@code Retryable} is a functional interface that can be used to implement any
21+
* generic block of code that can potentially be retried.
2122
*
2223
* <p>Used in conjunction with {@link RetryOperations}.
2324
*
2425
* @author Mahmoud Ben Hassine
26+
* @author Sam Brannen
2527
* @since 7.0
2628
* @param <R> the type of the result
2729
* @see RetryOperations
2830
*/
2931
@FunctionalInterface
30-
public interface RetryCallback<R> {
32+
public interface Retryable<R> {
3133

3234
/**
3335
* Method to execute and retry if needed.
34-
* @return the result of the callback
35-
* @throws Throwable if an error occurs during the execution of the callback
36+
* @return the result of the operation
37+
* @throws Throwable if an error occurs during the execution of the operation
3638
*/
3739
R run() throws Throwable;
3840

3941
/**
40-
* A unique, logical name for this callback, used to distinguish retries for
41-
* different business operations.
42-
* <p>Defaults to the fully-qualified class name.
43-
* @return the name of the callback
42+
* A unique, logical name for this retryable operation, used to distinguish
43+
* between retries for different business operations.
44+
* <p>Defaults to the fully-qualified class name of the implementation class.
45+
* @return the name of this retryable operation
4446
*/
4547
default String getName() {
4648
return getClass().getName();

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class RetryTemplateTests {
3737

3838
@Test
3939
void retryWithSuccess() throws Exception {
40-
RetryCallback<String> retryCallback = new RetryCallback<>() {
40+
Retryable<String> retryable = new Retryable<>() {
4141

4242
int failure;
4343

@@ -57,14 +57,14 @@ public String getName() {
5757

5858
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
5959

60-
assertThat(retryTemplate.execute(retryCallback)).isEqualTo("hello world");
60+
assertThat(retryTemplate.execute(retryable)).isEqualTo("hello world");
6161
}
6262

6363
@Test
6464
void retryWithFailure() {
6565
Exception exception = new Exception("Error while invoking greeting service");
6666

67-
RetryCallback<String> retryCallback = new RetryCallback<>() {
67+
Retryable<String> retryable = new Retryable<>() {
6868
@Override
6969
public String run() throws Exception {
7070
throw exception;
@@ -79,8 +79,8 @@ public String getName() {
7979
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
8080

8181
assertThatExceptionOfType(RetryException.class)
82-
.isThrownBy(() -> retryTemplate.execute(retryCallback))
83-
.withMessage("Retry policy for callback 'greeting service' exhausted; aborting execution")
82+
.isThrownBy(() -> retryTemplate.execute(retryable))
83+
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
8484
.withCause(exception);
8585
}
8686

@@ -96,7 +96,7 @@ public TechnicalException(String message) {
9696

9797
TechnicalException technicalException = new TechnicalException("Error while invoking greeting service");
9898

99-
RetryCallback<String> retryCallback = new RetryCallback<>() {
99+
Retryable<String> retryable = new Retryable<>() {
100100
@Override
101101
public String run() throws TechnicalException {
102102
throw technicalException;
@@ -126,8 +126,8 @@ public boolean shouldRetry(Throwable throwable) {
126126
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
127127

128128
assertThatExceptionOfType(RetryException.class)
129-
.isThrownBy(() -> retryTemplate.execute(retryCallback))
130-
.withMessage("Retry policy for callback 'greeting service' exhausted; aborting execution")
129+
.isThrownBy(() -> retryTemplate.execute(retryable))
130+
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
131131
.withCause(technicalException);
132132
}
133133

0 commit comments

Comments
 (0)