Search in sources :

Example 1 with MutableConvertibleValues

use of io.micronaut.core.convert.value.MutableConvertibleValues in project micronaut-core by micronaut-projects.

the class DefaultRetryInterceptor method intercept.

@Nullable
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    Optional<AnnotationValue<Retryable>> opt = context.findAnnotation(Retryable.class);
    if (!opt.isPresent()) {
        return context.proceed();
    }
    AnnotationValue<Retryable> retry = opt.get();
    boolean isCircuitBreaker = context.hasStereotype(CircuitBreaker.class);
    MutableRetryState retryState;
    AnnotationRetryStateBuilder retryStateBuilder = new AnnotationRetryStateBuilder(context);
    if (isCircuitBreaker) {
        long timeout = context.getValue(CircuitBreaker.class, "reset", Duration.class).map(Duration::toMillis).orElse(Duration.ofSeconds(DEFAULT_CIRCUIT_BREAKER_TIMEOUT_IN_MILLIS).toMillis());
        retryState = circuitContexts.computeIfAbsent(context.getExecutableMethod(), method -> new CircuitBreakerRetry(timeout, retryStateBuilder, context, eventPublisher));
    } else {
        retryState = (MutableRetryState) retryStateBuilder.build();
    }
    MutableConvertibleValues<Object> attrs = context.getAttributes();
    attrs.put(RetryState.class.getName(), retry);
    InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
    try {
        retryState.open();
        // Retry method call before we have actual Publisher/CompletionStage result
        Object result = retrySync(context, retryState, interceptedMethod);
        switch(interceptedMethod.resultType()) {
            case PUBLISHER:
                Flux<Object> reactiveSequence = Flux.from((Publisher<?>) result);
                return interceptedMethod.handleResult(reactiveSequence.onErrorResume(retryFlowable(context, retryState, reactiveSequence)).doOnNext(o -> retryState.close(null)));
            case COMPLETION_STAGE:
                CompletableFuture<Object> newFuture = new CompletableFuture<>();
                Supplier<CompletionStage<?>> retrySupplier = () -> interceptedMethod.interceptResultAsCompletionStage(this);
                ((CompletionStage<?>) result).whenComplete(retryCompletable(context, retryState, newFuture, retrySupplier));
                return interceptedMethod.handleResult(newFuture);
            case SYNCHRONOUS:
                retryState.close(null);
                return result;
            default:
                return interceptedMethod.unsupported();
        }
    } catch (Exception e) {
        return interceptedMethod.handleException(e);
    }
}
Also used : RetryState(io.micronaut.retry.RetryState) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) InterceptedMethod(io.micronaut.aop.InterceptedMethod) Function(java.util.function.Function) Supplier(java.util.function.Supplier) ExecutableMethod(io.micronaut.inject.ExecutableMethod) TaskExecutors(io.micronaut.scheduling.TaskExecutors) MethodInterceptor(io.micronaut.aop.MethodInterceptor) Nullable(io.micronaut.core.annotation.Nullable) Duration(java.time.Duration) Map(java.util.Map) Retryable(io.micronaut.retry.annotation.Retryable) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) BiConsumer(java.util.function.BiConsumer) MutableConvertibleValues(io.micronaut.core.convert.value.MutableConvertibleValues) ExecutorService(java.util.concurrent.ExecutorService) RetryEvent(io.micronaut.retry.event.RetryEvent) Logger(org.slf4j.Logger) Publisher(org.reactivestreams.Publisher) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ApplicationEventPublisher(io.micronaut.context.event.ApplicationEventPublisher) Singleton(jakarta.inject.Singleton) CircuitBreaker(io.micronaut.retry.annotation.CircuitBreaker) TimeUnit(java.util.concurrent.TimeUnit) Flux(reactor.core.publisher.Flux) ChronoUnit(java.time.temporal.ChronoUnit) CompletionStage(java.util.concurrent.CompletionStage) MethodInvocationContext(io.micronaut.aop.MethodInvocationContext) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Optional(java.util.Optional) InterceptPhase(io.micronaut.aop.InterceptPhase) Named(jakarta.inject.Named) InterceptedMethod(io.micronaut.aop.InterceptedMethod) CompletableFuture(java.util.concurrent.CompletableFuture) Retryable(io.micronaut.retry.annotation.Retryable) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) CompletionStage(java.util.concurrent.CompletionStage) RetryState(io.micronaut.retry.RetryState) Nullable(io.micronaut.core.annotation.Nullable)

Aggregations

InterceptPhase (io.micronaut.aop.InterceptPhase)1 InterceptedMethod (io.micronaut.aop.InterceptedMethod)1 MethodInterceptor (io.micronaut.aop.MethodInterceptor)1 MethodInvocationContext (io.micronaut.aop.MethodInvocationContext)1 ApplicationEventPublisher (io.micronaut.context.event.ApplicationEventPublisher)1 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)1 Nullable (io.micronaut.core.annotation.Nullable)1 MutableConvertibleValues (io.micronaut.core.convert.value.MutableConvertibleValues)1 ExecutableMethod (io.micronaut.inject.ExecutableMethod)1 RetryState (io.micronaut.retry.RetryState)1 CircuitBreaker (io.micronaut.retry.annotation.CircuitBreaker)1 Retryable (io.micronaut.retry.annotation.Retryable)1 RetryEvent (io.micronaut.retry.event.RetryEvent)1 TaskExecutors (io.micronaut.scheduling.TaskExecutors)1 Named (jakarta.inject.Named)1 Singleton (jakarta.inject.Singleton)1 Duration (java.time.Duration)1 ChronoUnit (java.time.temporal.ChronoUnit)1 Map (java.util.Map)1 Optional (java.util.Optional)1