Revise core retry support
This commit constitutes a first pass over the new core retry support. - Fix code and Javadoc formatting - Polish/fix Javadoc - Fix default FixedBackOff configuration in RetryTemplate - Consistent logging in RetryTemplate - Fix listener handling in CompositeRetryListener, allowing addListener() to work - Polish tests - Ensure RetryTemplateTests do not take over 30 seconds to execute See gh-34716
This commit is contained in:
@@ -16,27 +16,31 @@
|
||||
|
||||
package org.springframework.core.retry;
|
||||
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.retry.support.MaxRetryAttemptsPolicy;
|
||||
import org.springframework.util.backoff.FixedBackOff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link RetryTemplate}.
|
||||
*
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @author Sam Brannen
|
||||
* @since 7.0
|
||||
*/
|
||||
class RetryTemplateTests {
|
||||
|
||||
private final RetryTemplate retryTemplate = new RetryTemplate();
|
||||
|
||||
@Test
|
||||
void testRetryWithSuccess() throws Exception {
|
||||
// given
|
||||
void retryWithSuccess() throws Exception {
|
||||
RetryCallback<String> retryCallback = new RetryCallback<>() {
|
||||
|
||||
int failure;
|
||||
|
||||
@Override
|
||||
public String run() throws Exception {
|
||||
if (failure++ < 2) {
|
||||
@@ -50,21 +54,16 @@ class RetryTemplateTests {
|
||||
return "greeting service";
|
||||
}
|
||||
};
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(new MaxRetryAttemptsPolicy());
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff());
|
||||
|
||||
// when
|
||||
String result = retryTemplate.execute(retryCallback);
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
|
||||
|
||||
// then
|
||||
assertThat(result).isEqualTo("hello world");
|
||||
assertThat(retryTemplate.execute(retryCallback)).isEqualTo("hello world");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRetryWithFailure() {
|
||||
// given
|
||||
void retryWithFailure() {
|
||||
Exception exception = new Exception("Error while invoking greeting service");
|
||||
|
||||
RetryCallback<String> retryCallback = new RetryCallback<>() {
|
||||
@Override
|
||||
public String run() throws Exception {
|
||||
@@ -76,31 +75,27 @@ class RetryTemplateTests {
|
||||
return "greeting service";
|
||||
}
|
||||
};
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(new MaxRetryAttemptsPolicy());
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff());
|
||||
|
||||
// when
|
||||
ThrowingCallable throwingCallable = () -> retryTemplate.execute(retryCallback);
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
|
||||
|
||||
// then
|
||||
assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(RetryException.class)
|
||||
.hasMessage("Retry policy for callback 'greeting service' exhausted, aborting execution")
|
||||
.hasCause(exception);
|
||||
assertThatExceptionOfType(RetryException.class)
|
||||
.isThrownBy(() -> retryTemplate.execute(retryCallback))
|
||||
.withMessage("Retry policy for callback 'greeting service' exhausted; aborting execution")
|
||||
.withCause(exception);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRetrySpecificException() {
|
||||
// given
|
||||
void retrySpecificException() {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class TechnicalException extends Exception {
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
public TechnicalException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
final TechnicalException technicalException = new TechnicalException("Error while invoking greeting service");
|
||||
|
||||
TechnicalException technicalException = new TechnicalException("Error while invoking greeting service");
|
||||
|
||||
RetryCallback<String> retryCallback = new RetryCallback<>() {
|
||||
@Override
|
||||
public String run() throws TechnicalException {
|
||||
@@ -112,11 +107,14 @@ class RetryTemplateTests {
|
||||
return "greeting service";
|
||||
}
|
||||
};
|
||||
|
||||
MaxRetryAttemptsPolicy retryPolicy = new MaxRetryAttemptsPolicy() {
|
||||
@Override
|
||||
public RetryExecution start() {
|
||||
return new RetryExecution() {
|
||||
|
||||
int retryAttempts;
|
||||
|
||||
@Override
|
||||
public boolean shouldRetry(Throwable throwable) {
|
||||
return this.retryAttempts++ < 3 && throwable instanceof TechnicalException;
|
||||
@@ -124,18 +122,13 @@ class RetryTemplateTests {
|
||||
};
|
||||
}
|
||||
};
|
||||
RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setRetryPolicy(retryPolicy);
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff());
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(100, Long.MAX_VALUE));
|
||||
|
||||
// when
|
||||
ThrowingCallable throwingCallable = () -> retryTemplate.execute(retryCallback);
|
||||
|
||||
// then
|
||||
assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(RetryException.class)
|
||||
.hasMessage("Retry policy for callback 'greeting service' exhausted, aborting execution")
|
||||
.hasCause(technicalException);
|
||||
assertThatExceptionOfType(RetryException.class)
|
||||
.isThrownBy(() -> retryTemplate.execute(retryCallback))
|
||||
.withMessage("Retry policy for callback 'greeting service' exhausted; aborting execution")
|
||||
.withCause(technicalException);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,4 +76,5 @@ class ComposedRetryListenerTests {
|
||||
verify(this.listener1).onRetryPolicyExhaustion(retryExecution, exception);
|
||||
verify(this.listener2).onRetryPolicyExhaustion(retryExecution, exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.retry.RetryExecution;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,7 @@ import static org.mockito.Mockito.mock;
|
||||
class MaxRetryAttemptsPolicyTests {
|
||||
|
||||
@Test
|
||||
void testDefaultMaxRetryAttempts() {
|
||||
void defaultMaxRetryAttempts() {
|
||||
// given
|
||||
MaxRetryAttemptsPolicy retryPolicy = new MaxRetryAttemptsPolicy();
|
||||
Throwable throwable = mock();
|
||||
@@ -48,8 +48,10 @@ class MaxRetryAttemptsPolicyTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidMaxRetryAttempts() {
|
||||
assertThatThrownBy(() -> new MaxRetryAttemptsPolicy(-1))
|
||||
.hasMessage("Max retry attempts must be greater than zero");
|
||||
void invalidMaxRetryAttempts() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new MaxRetryAttemptsPolicy(-1))
|
||||
.withMessage("Max retry attempts must be greater than zero");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link MaxRetryDurationPolicy}.
|
||||
@@ -30,8 +30,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
class MaxRetryDurationPolicyTests {
|
||||
|
||||
@Test
|
||||
void testInvalidMaxRetryDuration() {
|
||||
assertThatThrownBy(() -> new MaxRetryDurationPolicy(Duration.ZERO))
|
||||
.hasMessage("Max retry duration must be positive");
|
||||
void invalidMaxRetryDuration() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new MaxRetryDurationPolicy(Duration.ZERO))
|
||||
.withMessage("Max retry duration must be positive");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class PredicateRetryPolicyTests {
|
||||
|
||||
@Test
|
||||
void testPredicateRetryPolicy() {
|
||||
void predicateRetryPolicy() {
|
||||
// given
|
||||
class MyException extends Exception {
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
Predicate<Throwable> predicate = throwable -> throwable instanceof MyException;
|
||||
Predicate<Throwable> predicate = MyException.class::isInstance;
|
||||
PredicateRetryPolicy retryPolicy = new PredicateRetryPolicy(predicate);
|
||||
|
||||
// when
|
||||
|
||||
Reference in New Issue
Block a user