Search in sources :

Example 1 with InterceptedMethod

use of io.micronaut.aop.InterceptedMethod in project resilience4j by resilience4j.

the class RateLimiterInterceptor method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    Optional<AnnotationValue<io.github.resilience4j.micronaut.annotation.RateLimiter>> opt = context.findAnnotation(io.github.resilience4j.micronaut.annotation.RateLimiter.class);
    if (!opt.isPresent()) {
        return context.proceed();
    }
    ExecutableMethod executableMethod = context.getExecutableMethod();
    final String name = executableMethod.stringValue(io.github.resilience4j.micronaut.annotation.RateLimiter.class, "name").orElse("default");
    RateLimiter rateLimiter = this.rateLimiterRegistry.rateLimiter(name);
    InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
    try {
        switch(interceptedMethod.resultType()) {
            case PUBLISHER:
                return interceptedMethod.handleResult(fallbackReactiveTypes(Flowable.fromPublisher(interceptedMethod.interceptResultAsPublisher()).compose(RateLimiterOperator.of(rateLimiter)), context));
            case COMPLETION_STAGE:
                return interceptedMethod.handleResult(fallbackForFuture(rateLimiter.executeCompletionStage(() -> {
                    try {
                        return interceptedMethod.interceptResultAsCompletionStage();
                    } catch (Exception e) {
                        throw new CompletionException(e);
                    }
                }), context));
            case SYNCHRONOUS:
                try {
                    return rateLimiter.executeCheckedSupplier(context::proceed);
                } catch (Throwable exception) {
                    return fallback(context, exception);
                }
            default:
                return interceptedMethod.unsupported();
        }
    } catch (Exception e) {
        return interceptedMethod.handleException(e);
    }
}
Also used : ExecutableMethod(io.micronaut.inject.ExecutableMethod) InterceptedMethod(io.micronaut.aop.InterceptedMethod) RateLimiter(io.github.resilience4j.ratelimiter.RateLimiter) CompletionException(java.util.concurrent.CompletionException) CompletionException(java.util.concurrent.CompletionException) AnnotationValue(io.micronaut.core.annotation.AnnotationValue)

Example 2 with InterceptedMethod

use of io.micronaut.aop.InterceptedMethod in project resilience4j by resilience4j.

the class BulkheadInterceptor method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    Optional<AnnotationValue<io.github.resilience4j.micronaut.annotation.Bulkhead>> opt = context.findAnnotation(io.github.resilience4j.micronaut.annotation.Bulkhead.class);
    if (!opt.isPresent()) {
        return context.proceed();
    }
    final io.github.resilience4j.micronaut.annotation.Bulkhead.Type type = opt.get().enumValue("type", io.github.resilience4j.micronaut.annotation.Bulkhead.Type.class).orElse(io.github.resilience4j.micronaut.annotation.Bulkhead.Type.SEMAPHORE);
    if (type == io.github.resilience4j.micronaut.annotation.Bulkhead.Type.THREADPOOL) {
        return handleThreadPoolBulkhead(context, opt.get());
    } else {
        final String name = opt.get().stringValue("name").orElse("default");
        Bulkhead bulkhead = this.bulkheadRegistry.bulkhead(name);
        InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
        try {
            switch(interceptedMethod.resultType()) {
                case PUBLISHER:
                    return interceptedMethod.handleResult(fallbackReactiveTypes(Flowable.fromPublisher(interceptedMethod.interceptResultAsPublisher()).compose(BulkheadOperator.of(bulkhead)), context));
                case COMPLETION_STAGE:
                    return interceptedMethod.handleResult(fallbackForFuture(bulkhead.executeCompletionStage(() -> {
                        try {
                            return interceptedMethod.interceptResultAsCompletionStage();
                        } catch (Exception e) {
                            throw new CompletionException(e);
                        }
                    }), context));
                case SYNCHRONOUS:
                    try {
                        return bulkhead.executeCheckedSupplier(context::proceed);
                    } catch (Throwable exception) {
                        return fallback(context, exception);
                    }
                default:
                    return interceptedMethod.unsupported();
            }
        } catch (Exception e) {
            return interceptedMethod.handleException(e);
        }
    }
}
Also used : InterceptedMethod(io.micronaut.aop.InterceptedMethod) CompletionException(java.util.concurrent.CompletionException) ExecutionException(java.util.concurrent.ExecutionException) CompletionException(java.util.concurrent.CompletionException) AnnotationValue(io.micronaut.core.annotation.AnnotationValue)

Example 3 with InterceptedMethod

use of io.micronaut.aop.InterceptedMethod in project resilience4j by resilience4j.

the class RetryInterceptor method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    Optional<AnnotationValue<io.github.resilience4j.micronaut.annotation.Retry>> opt = context.findAnnotation(io.github.resilience4j.micronaut.annotation.Retry.class);
    if (!opt.isPresent()) {
        return context.proceed();
    }
    ExecutableMethod executableMethod = context.getExecutableMethod();
    final String name = executableMethod.stringValue(io.github.resilience4j.micronaut.annotation.Retry.class, "name").orElse("default");
    Retry retry = retryRegistry.retry(name);
    InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
    try {
        switch(interceptedMethod.resultType()) {
            case PUBLISHER:
                return interceptedMethod.handleResult(fallbackReactiveTypes(Flowable.fromPublisher(interceptedMethod.interceptResultAsPublisher()).compose(RetryTransformer.of(retry)), context));
            case COMPLETION_STAGE:
                return interceptedMethod.handleResult(fallbackForFuture(retry.executeCompletionStage(executorService, () -> {
                    try {
                        return interceptedMethod.interceptResultAsCompletionStage();
                    } catch (Exception e) {
                        throw new CompletionException(e);
                    }
                }), context));
            case SYNCHRONOUS:
                try {
                    return retry.executeCheckedSupplier(context::proceed);
                } catch (Throwable exception) {
                    return fallback(context, exception);
                }
            default:
                return interceptedMethod.unsupported();
        }
    } catch (Exception e) {
        return interceptedMethod.handleException(e);
    }
}
Also used : ExecutableMethod(io.micronaut.inject.ExecutableMethod) InterceptedMethod(io.micronaut.aop.InterceptedMethod) CompletionException(java.util.concurrent.CompletionException) CompletionException(java.util.concurrent.CompletionException) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Retry(io.github.resilience4j.retry.Retry)

Example 4 with InterceptedMethod

use of io.micronaut.aop.InterceptedMethod in project micronaut-micrometer by micronaut-projects.

the class CountedInterceptor method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    final AnnotationMetadata metadata = context.getAnnotationMetadata();
    final String metricName = metadata.stringValue(Counted.class).orElse(DEFAULT_METRIC_NAME);
    if (StringUtils.isNotEmpty(metricName)) {
        InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
        try {
            InterceptedMethod.ResultType resultType = interceptedMethod.resultType();
            switch(resultType) {
                case PUBLISHER:
                    Object interceptResult = context.proceed();
                    if (interceptResult == null) {
                        return null;
                    }
                    Object reactiveResult;
                    if (context.getReturnType().isSingleResult()) {
                        Mono<?> single = Publishers.convertPublisher(interceptResult, Mono.class);
                        reactiveResult = single.doOnError(throwable -> doCount(metadata, metricName, throwable)).doOnSuccess(o -> doCount(metadata, metricName, null));
                    } else {
                        Flux<?> flowable = Publishers.convertPublisher(interceptResult, Flux.class);
                        reactiveResult = flowable.doOnError(throwable -> doCount(metadata, metricName, throwable)).doOnComplete(() -> doCount(metadata, metricName, null));
                    }
                    return Publishers.convertPublisher(reactiveResult, context.getReturnType().getType());
                case COMPLETION_STAGE:
                    CompletionStage<?> completionStage = interceptedMethod.interceptResultAsCompletionStage();
                    CompletionStage<?> completionStageResult = completionStage.whenComplete((o, throwable) -> doCount(metadata, metricName, throwable));
                    return interceptedMethod.handleResult(completionStageResult);
                case SYNCHRONOUS:
                    final Object result = context.proceed();
                    try {
                        return result;
                    } finally {
                        if (metadata.isFalse(Counted.class, "recordFailuresOnly")) {
                            doCount(metadata, metricName, null);
                        }
                    }
                default:
                    return interceptedMethod.unsupported();
            }
        } catch (Exception e) {
            try {
                return interceptedMethod.handleException(e);
            } finally {
                doCount(metadata, metricName, e);
            }
        }
    }
    return context.proceed();
}
Also used : Counter(io.micrometer.core.instrument.Counter) RequiresMetrics(io.micronaut.configuration.metrics.annotation.RequiresMetrics) Publishers(io.micronaut.core.async.publisher.Publishers) Mono(reactor.core.publisher.Mono) InterceptedMethod(io.micronaut.aop.InterceptedMethod) InterceptorBean(io.micronaut.aop.InterceptorBean) StringUtils(io.micronaut.core.util.StringUtils) Flux(reactor.core.publisher.Flux) Counted(io.micrometer.core.annotation.Counted) CompletionStage(java.util.concurrent.CompletionStage) EXCEPTION_TAG(io.micrometer.core.aop.TimedAspect.EXCEPTION_TAG) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) MethodInterceptor(io.micronaut.aop.MethodInterceptor) MethodInvocationContext(io.micronaut.aop.MethodInvocationContext) Nullable(io.micronaut.core.annotation.Nullable) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Counted(io.micrometer.core.annotation.Counted) InterceptedMethod(io.micronaut.aop.InterceptedMethod) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Example 5 with InterceptedMethod

use of io.micronaut.aop.InterceptedMethod in project resilience4j by resilience4j.

the class BulkheadInterceptor method handleThreadPoolBulkhead.

private CompletionStage<?> handleThreadPoolBulkhead(MethodInvocationContext<Object, Object> context, AnnotationValue<io.github.resilience4j.micronaut.annotation.Bulkhead> bulkheadAnnotationValue) {
    final String name = bulkheadAnnotationValue.stringValue().orElse("default");
    ThreadPoolBulkhead bulkhead = this.threadPoolBulkheadRegistry.bulkhead(name);
    InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
    if (interceptedMethod.resultType() == InterceptedMethod.ResultType.COMPLETION_STAGE) {
        try {
            return this.fallbackForFuture(bulkhead.executeSupplier(() -> {
                try {
                    return ((CompletableFuture<?>) context.proceed()).get();
                } catch (ExecutionException e) {
                    throw new CompletionException(e.getCause());
                } catch (Throwable e) {
                    throw new CompletionException(e);
                }
            }), context);
        } catch (BulkheadFullException ex) {
            CompletableFuture<?> future = new CompletableFuture<>();
            future.completeExceptionally(ex);
            return future;
        }
    }
    throw new IllegalStateException("ThreadPool bulkhead is only applicable for completable futures");
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) InterceptedMethod(io.micronaut.aop.InterceptedMethod) CompletionException(java.util.concurrent.CompletionException) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

InterceptedMethod (io.micronaut.aop.InterceptedMethod)9 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)6 CompletionException (java.util.concurrent.CompletionException)6 ExecutableMethod (io.micronaut.inject.ExecutableMethod)5 InterceptorBean (io.micronaut.aop.InterceptorBean)2 MethodInterceptor (io.micronaut.aop.MethodInterceptor)2 MethodInvocationContext (io.micronaut.aop.MethodInvocationContext)2 StringUtils (io.micronaut.core.util.StringUtils)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 CircuitBreaker (io.github.resilience4j.circuitbreaker.CircuitBreaker)1 RateLimiter (io.github.resilience4j.ratelimiter.RateLimiter)1 Retry (io.github.resilience4j.retry.Retry)1 TimeLimiter (io.github.resilience4j.timelimiter.TimeLimiter)1 Counted (io.micrometer.core.annotation.Counted)1 EXCEPTION_TAG (io.micrometer.core.aop.TimedAspect.EXCEPTION_TAG)1 Counter (io.micrometer.core.instrument.Counter)1 MeterRegistry (io.micrometer.core.instrument.MeterRegistry)1 Cache (io.micronaut.caffeine.cache.Cache)1 Caffeine (io.micronaut.caffeine.cache.Caffeine)1 KafkaClient (io.micronaut.configuration.kafka.annotation.KafkaClient)1