All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xyz.block.ftl.deployment.SubscriptionProcessor Maven / Gradle / Ivy

The newest version!
package xyz.block.ftl.deployment;

import java.util.HashMap;
import java.util.Map;

import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.DotName;
import org.jboss.jandex.MethodInfo;
import org.jboss.logging.Logger;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import xyz.block.ftl.Retry;
import xyz.block.ftl.Subscription;
import xyz.block.ftl.v1.schema.Decl;
import xyz.block.ftl.v1.schema.Metadata;
import xyz.block.ftl.v1.schema.MetadataRetry;
import xyz.block.ftl.v1.schema.MetadataSubscriber;
import xyz.block.ftl.v1.schema.Ref;

public class SubscriptionProcessor {

    private static final Logger log = Logger.getLogger(SubscriptionProcessor.class);

    @BuildStep
    SubscriptionMetaAnnotationsBuildItem subscriptionAnnotations(CombinedIndexBuildItem combinedIndexBuildItem,
            ModuleNameBuildItem moduleNameBuildItem) {
        Map annotations = new HashMap<>();
        for (var subscriptions : combinedIndexBuildItem.getComputingIndex().getAnnotations(Subscription.class)) {
            if (subscriptions.target().kind() != AnnotationTarget.Kind.CLASS) {
                continue;
            }
            annotations.put(subscriptions.target().asClass().name(),
                    SubscriptionMetaAnnotationsBuildItem.fromJandex(subscriptions, moduleNameBuildItem.getModuleName()));
        }
        return new SubscriptionMetaAnnotationsBuildItem(annotations);
    }

    @BuildStep
    public void registerSubscriptions(CombinedIndexBuildItem index,
            ModuleNameBuildItem moduleNameBuildItem,
            BuildProducer additionalBeanBuildItemBuildProducer,
            SubscriptionMetaAnnotationsBuildItem subscriptionMetaAnnotationsBuildItem,
            BuildProducer schemaContributorBuildItems) throws Exception {
        AdditionalBeanBuildItem.Builder beans = AdditionalBeanBuildItem.builder().setUnremovable();
        var moduleName = moduleNameBuildItem.getModuleName();
        for (var subscription : index.getIndex().getAnnotations(FTLDotNames.SUBSCRIPTION)) {
            var info = SubscriptionMetaAnnotationsBuildItem.fromJandex(subscription, moduleName);
            if (subscription.target().kind() != AnnotationTarget.Kind.METHOD) {
                continue;
            }
            var method = subscription.target().asMethod();
            String className = method.declaringClass().name().toString();
            beans.addBeanClass(className);
            schemaContributorBuildItems.produce(generateSubscription(method, className, info));
        }
        for (var metaSub : subscriptionMetaAnnotationsBuildItem.getAnnotations().entrySet()) {
            for (var subscription : index.getIndex().getAnnotations(metaSub.getKey())) {
                if (subscription.target().kind() != AnnotationTarget.Kind.METHOD) {
                    log.warnf("Subscription annotation on non-method target: %s", subscription.target());
                    continue;
                }
                var method = subscription.target().asMethod();

                String className = method.declaringClass().name().toString();
                beans.addBeanClass(className);
                schemaContributorBuildItems.produce(generateSubscription(method,
                        className,
                        metaSub.getValue()));
            }

        }
        additionalBeanBuildItemBuildProducer.produce(beans.build());
    }

    private SchemaContributorBuildItem generateSubscription(MethodInfo method, String className,
            SubscriptionMetaAnnotationsBuildItem.SubscriptionAnnotation info) {
        return new SchemaContributorBuildItem(moduleBuilder -> {

            moduleBuilder.addDecls(Decl.newBuilder()
                    .setSubscription(xyz.block.ftl.v1.schema.Subscription.newBuilder()
                            .setName(info.name())
                            .setTopic(Ref.newBuilder().setName(info.topic()).setModule(info.module()).build()))
                    .build());
            moduleBuilder.registerVerbMethod(method, className, false, ModuleBuilder.BodyType.REQUIRED, (builder -> {
                builder.addMetadata(Metadata.newBuilder().setSubscriber(MetadataSubscriber.newBuilder().setName(info.name())));
                if (method.hasAnnotation(Retry.class)) {
                    RetryRecord retry = RetryRecord.fromJandex(method.annotation(Retry.class), moduleBuilder.getModuleName());

                    MetadataRetry.Builder retryBuilder = MetadataRetry.newBuilder();
                    if (!retry.catchVerb().isEmpty()) {
                        retryBuilder.setCatch(Ref.newBuilder().setModule(retry.catchModule())
                                .setName(retry.catchVerb()).build());
                    }
                    retryBuilder.setCount(retry.count())
                            .setMaxBackoff(retry.maxBackoff())
                            .setMinBackoff(retry.minBackoff());
                    builder.addMetadata(Metadata.newBuilder().setRetry(retryBuilder).build());
                }
            }));
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy