Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to SmallRye Fault Tolerance 6.4.0 #42031

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<smallrye-metrics.version>4.0.0</smallrye-metrics.version>
<smallrye-open-api.version>3.10.0</smallrye-open-api.version>
<smallrye-graphql.version>2.9.0</smallrye-graphql.version>
<smallrye-fault-tolerance.version>6.3.0</smallrye-fault-tolerance.version>
<smallrye-fault-tolerance.version>6.4.0</smallrye-fault-tolerance.version>
<smallrye-jwt.version>4.5.3</smallrye-jwt.version>
<smallrye-context-propagation.version>2.1.2</smallrye-context-propagation.version>
<smallrye-reactive-streams-operators.version>1.0.13</smallrye-reactive-streams-operators.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import io.smallrye.faulttolerance.FaultToleranceInterceptor;
import io.smallrye.faulttolerance.api.ApplyFaultTolerance;
import io.smallrye.faulttolerance.api.AsynchronousNonBlocking;
import io.smallrye.faulttolerance.api.BeforeRetry;
import io.smallrye.faulttolerance.api.BeforeRetryHandler;
import io.smallrye.faulttolerance.api.CircuitBreakerName;
import io.smallrye.faulttolerance.api.CustomBackoff;
import io.smallrye.faulttolerance.api.CustomBackoffStrategy;
Expand All @@ -28,6 +30,7 @@ public final class DotNames {
public static final DotName OBJECT = DotName.createSimple(Object.class);

public static final DotName FALLBACK_HANDLER = DotName.createSimple(FallbackHandler.class);
public static final DotName BEFORE_RETRY_HANDLER = DotName.createSimple(BeforeRetryHandler.class);

public static final DotName FAULT_TOLERANCE_INTERCEPTOR = DotName.createSimple(FaultToleranceInterceptor.class);

Expand All @@ -54,9 +57,11 @@ public final class DotNames {
public static final DotName CUSTOM_BACKOFF = DotName.createSimple(CustomBackoff.class);
public static final DotName CUSTOM_BACKOFF_STRATEGY = DotName.createSimple(CustomBackoffStrategy.class);
public static final DotName RETRY_WHEN = DotName.createSimple(RetryWhen.class);
public static final DotName BEFORE_RETRY = DotName.createSimple(BeforeRetry.class);

// certain SmallRye annotations (@CircuitBreakerName, @[Non]Blocking, @*Backoff, @RetryWhen) alone do _not_ trigger
// the fault tolerance interceptor, only in combination with other fault tolerance annotations
// certain SmallRye annotations (@CircuitBreakerName, @[Non]Blocking, @*Backoff, @RetryWhen, @BeforeRetry)
// do _not_ trigger the fault tolerance interceptor alone, only in combination
// with other fault tolerance annotations
public static final Set<DotName> FT_ANNOTATIONS = Set.of(APPLY_FAULT_TOLERANCE, ASYNCHRONOUS,
ASYNCHRONOUS_NON_BLOCKING, BULKHEAD, CIRCUIT_BREAKER, FALLBACK, RATE_LIMIT, RETRY, TIMEOUT);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.smallrye.common.annotation.NonBlocking;
import io.smallrye.faulttolerance.api.ApplyFaultTolerance;
import io.smallrye.faulttolerance.api.AsynchronousNonBlocking;
import io.smallrye.faulttolerance.api.BeforeRetry;
import io.smallrye.faulttolerance.api.CircuitBreakerName;
import io.smallrye.faulttolerance.api.CustomBackoff;
import io.smallrye.faulttolerance.api.ExponentialBackoff;
Expand Down Expand Up @@ -136,6 +137,7 @@ FaultToleranceMethod createFaultToleranceMethod(ClassInfo beanClass, MethodInfo
result.exponentialBackoff = getAnnotation(ExponentialBackoff.class, method, beanClass, annotationsPresentDirectly);
result.fibonacciBackoff = getAnnotation(FibonacciBackoff.class, method, beanClass, annotationsPresentDirectly);
result.retryWhen = getAnnotation(RetryWhen.class, method, beanClass, annotationsPresentDirectly);
result.beforeRetry = getAnnotation(BeforeRetry.class, method, beanClass, annotationsPresentDirectly);

result.annotationsPresentDirectly = annotationsPresentDirectly;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import io.quarkus.runtime.metrics.MetricsFactory;
import io.quarkus.smallrye.faulttolerance.deployment.devui.FaultToleranceInfoBuildItem;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusAsyncExecutorProvider;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusBeforeRetryHandlerProvider;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusExistingCircuitBreakerNames;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusFallbackHandlerProvider;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusFaultToleranceOperationProvider;
Expand Down Expand Up @@ -102,19 +103,22 @@ public void build(BuildProducer<AnnotationsTransformerBuildItem> annotationsTran

IndexView index = combinedIndexBuildItem.getIndex();

// Add reflective access to fallback handlers
Set<String> fallbackHandlers = new HashSet<>();
// Add reflective access to fallback handlers and before retry handlers
Set<String> handlers = new HashSet<>();
for (ClassInfo implementor : index.getAllKnownImplementors(DotNames.FALLBACK_HANDLER)) {
fallbackHandlers.add(implementor.name().toString());
handlers.add(implementor.name().toString());
}
if (!fallbackHandlers.isEmpty()) {
AdditionalBeanBuildItem.Builder fallbackHandlersBeans = AdditionalBeanBuildItem.builder()
for (ClassInfo implementor : index.getAllKnownImplementors(DotNames.BEFORE_RETRY_HANDLER)) {
handlers.add(implementor.name().toString());
}
if (!handlers.isEmpty()) {
AdditionalBeanBuildItem.Builder handlerBeans = AdditionalBeanBuildItem.builder()
.setDefaultScope(BuiltinScope.DEPENDENT.getName());
for (String fallbackHandler : fallbackHandlers) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(fallbackHandler).methods().build());
fallbackHandlersBeans.addBeanClass(fallbackHandler);
for (String handler : handlers) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(handler).methods().build());
handlerBeans.addBeanClass(handler);
}
beans.produce(fallbackHandlersBeans.build());
beans.produce(handlerBeans.build());
}
// Add reflective access to fallback methods
for (AnnotationInstance annotation : index.getAnnotations(DotNames.FALLBACK)) {
Expand Down Expand Up @@ -200,6 +204,7 @@ public void transform(TransformationContext context) {
ExecutorHolder.class,
StrategyCache.class,
QuarkusFallbackHandlerProvider.class,
QuarkusBeforeRetryHandlerProvider.class,
QuarkusAsyncExecutorProvider.class,
CircuitBreakerMaintenanceImpl.class,
RequestContextIntegration.class,
Expand Down Expand Up @@ -376,6 +381,11 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
exceptions.add(new DefinitionException("@RetryWhen present on '" + it.target() + "', but @Retry is missing"));
}
}
for (AnnotationInstance it : index.getAnnotations(DotNames.BEFORE_RETRY)) {
if (!annotationStore.hasAnnotation(it.target(), DotNames.RETRY)) {
exceptions.add(new DefinitionException("@BeforeRetry present on '" + it.target() + "', but @Retry is missing"));
}
}

if (!exceptions.isEmpty()) {
errors.produce(new ValidationPhaseBuildItem.ValidationErrorBuildItem(exceptions));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export class QwcFaultToleranceMethods extends LitElement {
${guardedMethod.FibonacciBackoff ? this._renderFibonacciBackoff(guardedMethod.FibonacciBackoff) : html``}
${guardedMethod.CustomBackoff ? this._renderCustomBackoff(guardedMethod.CustomBackoff) : html``}
${guardedMethod.RetryWhen ? this._renderRetryWhen(guardedMethod.RetryWhen) : html``}
${guardedMethod.BeforeRetry ? this._renderBeforeRetry(guardedMethod.BeforeRetry) : html``}
${guardedMethod.Timeout ? this._renderTimeout(guardedMethod.Timeout) : html``}
</vaadin-vertical-layout>
`;
Expand Down Expand Up @@ -189,6 +190,15 @@ export class QwcFaultToleranceMethods extends LitElement {
`;
}

_renderBeforeRetry(beforeRetry) {
return html`
<span>
&rarrhk;
@BeforeRetry(value = ${beforeRetry.value}, methodName = ${beforeRetry.methodName})
</span>
`;
}

_renderTimeout(timeout) {
return html`
<span>@Timeout(${timeout.value} ${timeout.valueUnit})</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;

import org.eclipse.microprofile.faulttolerance.ExecutionContext;
import org.eclipse.microprofile.faulttolerance.Retry;

import io.smallrye.faulttolerance.api.BeforeRetry;
import io.smallrye.faulttolerance.api.BeforeRetryHandler;

@Dependent
public class BeforeRetryHandlerService {
static final Set<Integer> ids = ConcurrentHashMap.newKeySet();

@Retry
@BeforeRetry(MyBeforeRetryHandler.class)
public void hello() {
throw new IllegalArgumentException();
}

static class MyBeforeRetryHandler implements BeforeRetryHandler {
@Inject
MyDependency dep;

@Override
public void handle(ExecutionContext context) {
ids.add(dep.id);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class BeforeRetryHandlerTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(BeforeRetryHandlerService.class, MyDependency.class));

@Inject
BeforeRetryHandlerService service;

@Test
public void test() {
assertThrows(IllegalArgumentException.class, service::hello);
assertThat(BeforeRetryHandlerService.ids)
.hasSize(3)
.containsExactly(1, 2, 3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import jakarta.enterprise.context.Dependent;

import org.eclipse.microprofile.faulttolerance.Retry;

import io.smallrye.faulttolerance.api.BeforeRetry;

@Dependent
public class BeforeRetryMethodService {
static final Set<Integer> ids = ConcurrentHashMap.newKeySet();
private static final AtomicInteger counter = new AtomicInteger();

@Retry
@BeforeRetry(methodName = "beforeRetry")
public void hello() {
throw new IllegalArgumentException();
}

void beforeRetry() {
ids.add(counter.incrementAndGet());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class BeforeRetryMethodTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(BeforeRetryMethodService.class));

@Inject
BeforeRetryMethodService service;

@Test
public void test() {
assertThrows(IllegalArgumentException.class, service::hello);
assertThat(BeforeRetryMethodService.ids)
.hasSize(3)
.containsExactly(1, 2, 3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import jakarta.enterprise.context.Dependent;

import org.eclipse.microprofile.faulttolerance.ExecutionContext;
import org.eclipse.microprofile.faulttolerance.Retry;

import io.smallrye.faulttolerance.api.BeforeRetry;
import io.smallrye.faulttolerance.api.BeforeRetryHandler;

@Dependent
public class BothValueAndMethodNameSetService {
@Retry
@BeforeRetry(value = MyHandler.class, methodName = "beforeRetry")
public void hello() {
throw new IllegalArgumentException();
}

void beforeRetry() {
}

static class MyHandler implements BeforeRetryHandler {
@Override
public void handle(ExecutionContext context) {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import jakarta.enterprise.inject.spi.DeploymentException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class BothValueAndMethodNameSetTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(BothValueAndMethodNameSetService.class))
.assertException(e -> {
assertEquals(DeploymentException.class, e.getClass());
assertTrue(e.getMessage().contains("Invalid @BeforeRetry"));
assertTrue(e.getMessage().contains(
"before retry handler class and before retry method can't be specified both at the same time"));
});

@Test
public void test() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import java.util.concurrent.atomic.AtomicInteger;

import jakarta.enterprise.context.Dependent;

@Dependent
public class MyDependency {
private static final AtomicInteger counter = new AtomicInteger();

public final int id = counter.incrementAndGet();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import jakarta.enterprise.context.Dependent;

import org.eclipse.microprofile.faulttolerance.Retry;

import io.smallrye.faulttolerance.api.BeforeRetry;

@Dependent
public class NoBeforeRetryMethodFoundService {
@Retry
@BeforeRetry(methodName = "beforeRetry")
public void hello() {
throw new IllegalArgumentException();
}

public int beforeRetry(int param) {
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.smallrye.faulttolerance.test.retry.beforeretry;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import jakarta.enterprise.inject.spi.DeploymentException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class NoBeforeRetryMethodFoundTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(NoBeforeRetryMethodFoundService.class))
.assertException(e -> {
assertEquals(DeploymentException.class, e.getClass());
assertTrue(e.getMessage().contains("Invalid @BeforeRetry"));
assertTrue(e.getMessage().contains("can't find before retry method"));
});

@Test
public void test() {
}
}
Loading
Loading