Expose RetryException#getRetryCount() and accept maxAttempts(0)

Closes gh-35351
Closes gh-35362
This commit is contained in:
Juergen Hoeller
2025-08-20 23:15:40 +02:00
parent 472f844256
commit 2489cced0f
8 changed files with 130 additions and 57 deletions
@@ -189,6 +189,26 @@ class ReactiveRetryInterceptorTests {
assertThat(target.counter.get()).isEqualTo(2);
}
@Test
void adaptReactiveResultWithZeroAttempts() {
// Test minimal retry configuration: maxAttempts=1, delay=0, jitter=0, multiplier=1.0, maxDelay=0
MinimalRetryBean target = new MinimalRetryBean();
ProxyFactory pf = new ProxyFactory();
pf.setTarget(target);
pf.addAdvice(new SimpleRetryInterceptor(
new MethodRetrySpec((m, t) -> true, 0, Duration.ZERO, Duration.ZERO, 1.0, Duration.ZERO)));
MinimalRetryBean proxy = (MinimalRetryBean) pf.getProxy();
// Should execute only 1 time, because maxAttempts=0 means initial call only
assertThatIllegalStateException()
.isThrownBy(() -> proxy.retryOperation().block())
.satisfies(isRetryExhaustedException())
.havingCause()
.isInstanceOf(IOException.class)
.withMessage("1");
assertThat(target.counter.get()).isEqualTo(1);
}
@Test
void adaptReactiveResultWithZeroDelayAndJitter() {
// Test case where delay=0 and jitter>0
@@ -194,6 +194,31 @@ class RetryInterceptorTests {
assertThat(target.counter).isEqualTo(6);
}
@Test
void withPostProcessorForClassWithZeroAttempts() {
Properties props = new Properties();
props.setProperty("delay", "10");
props.setProperty("jitter", "5");
props.setProperty("multiplier", "2.0");
props.setProperty("maxDelay", "40");
props.setProperty("limitedAttempts", "0");
GenericApplicationContext ctx = new GenericApplicationContext();
ctx.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("props", props));
ctx.registerBeanDefinition("bean", new RootBeanDefinition(AnnotatedClassBeanWithStrings.class));
ctx.registerBeanDefinition("bpp", new RootBeanDefinition(RetryAnnotationBeanPostProcessor.class));
ctx.refresh();
AnnotatedClassBeanWithStrings proxy = ctx.getBean(AnnotatedClassBeanWithStrings.class);
AnnotatedClassBeanWithStrings target = (AnnotatedClassBeanWithStrings) AopProxyUtils.getSingletonTarget(proxy);
assertThatIOException().isThrownBy(proxy::retryOperation).withMessage("3");
assertThat(target.counter).isEqualTo(3);
assertThatIOException().isThrownBy(proxy::otherOperation);
assertThat(target.counter).isEqualTo(4);
assertThatIOException().isThrownBy(proxy::overrideOperation);
assertThat(target.counter).isEqualTo(5);
}
@Test
void withEnableAnnotation() throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();