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

io.quarkus.smallrye.graphql.runtime.spi.datafetcher.AbstractAsyncDataFetcher Maven / Gradle / Ivy

There is a newer version: 3.17.0.CR1
Show newest version
package io.quarkus.smallrye.graphql.runtime.spi.datafetcher;

import java.util.List;
import java.util.concurrent.CompletionStage;

import org.eclipse.microprofile.graphql.GraphQLException;

import graphql.execution.DataFetcherResult;
import graphql.schema.DataFetchingEnvironment;
import io.quarkus.arc.Arc;
import io.quarkus.arc.ManagedContext;
import io.smallrye.graphql.SmallRyeGraphQLServerMessages;
import io.smallrye.graphql.api.Context;
import io.smallrye.graphql.execution.context.SmallRyeContextManager;
import io.smallrye.graphql.execution.datafetcher.AbstractDataFetcher;
import io.smallrye.graphql.schema.model.Operation;
import io.smallrye.graphql.schema.model.Type;
import io.smallrye.graphql.transformation.AbstractDataFetcherException;
import io.smallrye.mutiny.Uni;

public abstract class AbstractAsyncDataFetcher extends AbstractDataFetcher {

    public AbstractAsyncDataFetcher(Operation operation, Type type) {
        super(operation, type);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected  O invokeAndTransform(
            Context c,
            DataFetchingEnvironment dfe,
            DataFetcherResult.Builder resultBuilder,
            Object[] transformedArguments) throws Exception {

        ManagedContext requestContext = Arc.container().requestContext();
        try {
            RequestContextHelper.reactivate(requestContext, dfe);
            Uni uni = handleUserMethodCall(dfe, transformedArguments);
            return (O) uni
                    .onItemOrFailure()
                    .transformToUni((result, throwable, emitter) -> {

                        emitter.onTermination(() -> {
                            deactivate(requestContext);
                        });

                        if (throwable != null) {
                            eventEmitter.fireOnDataFetchError(c, throwable);
                            if (throwable instanceof GraphQLException) {
                                GraphQLException graphQLException = (GraphQLException) throwable;
                                errorResultHelper.appendPartialResult(resultBuilder, dfe, graphQLException);
                            } else if (throwable instanceof Exception) {
                                emitter.fail(SmallRyeGraphQLServerMessages.msg.dataFetcherException(operation, throwable));
                                return;
                            } else if (throwable instanceof Error) {
                                emitter.fail(throwable);
                                return;
                            }
                        } else {
                            try {
                                resultBuilder.data(fieldHelper.transformOrAdaptResponse(result, dfe));
                            } catch (AbstractDataFetcherException te) {
                                te.appendDataFetcherResult(resultBuilder, dfe);
                            }
                        }
                        emitter.complete(resultBuilder.build());
                    })
                    .onCancellation().invoke(() -> {
                        deactivate(requestContext);
                    })
                    .onTermination().invoke(() -> {
                        deactivate(requestContext);
                    })
                    .subscribe()
                    .asCompletionStage();
        } finally {
            deactivate(requestContext);
        }
    }

    private void deactivate(ManagedContext requestContext) {
        SmallRyeContextManager.clearCurrentSmallRyeContext();
        requestContext.deactivate();
    }

    protected abstract Uni handleUserMethodCall(DataFetchingEnvironment dfe, final Object[] transformedArguments)
            throws Exception;

    @Override
    @SuppressWarnings("unchecked")
    protected  O invokeFailure(DataFetcherResult.Builder resultBuilder) {
        return (O) Uni.createFrom()
                .item(resultBuilder::build)
                .subscribe()
                .asCompletionStage();
    }

    @Override
    @SuppressWarnings("unchecked")
    protected CompletionStage> invokeBatch(DataFetchingEnvironment dfe, Object[] arguments) {
        ManagedContext requestContext = Arc.container().requestContext();
        try {
            RequestContextHelper.reactivate(requestContext, dfe);
            return handleUserBatchLoad(dfe, arguments)
                    .subscribe().asCompletionStage();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            requestContext.deactivate();
        }
    }

    protected abstract Uni> handleUserBatchLoad(DataFetchingEnvironment dfe, final Object[] arguments)
            throws Exception;
}