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

io.quarkus.smallrye.graphql.runtime.spi.datafetcher.QuarkusUniDataFetcher 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.Callable;

import graphql.schema.DataFetchingEnvironment;
import io.quarkus.arc.Arc;
import io.smallrye.context.SmallRyeThreadContext;
import io.smallrye.graphql.schema.model.Operation;
import io.smallrye.graphql.schema.model.Type;
import io.smallrye.mutiny.Uni;
import io.vertx.core.Context;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;

public class QuarkusUniDataFetcher extends AbstractAsyncDataFetcher {

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

    @Override
    protected Uni handleUserMethodCall(DataFetchingEnvironment dfe, Object[] transformedArguments) throws Exception {
        Context vc = Vertx.currentContext();
        if (runBlocking(dfe) || !BlockingHelper.nonBlockingShouldExecuteBlocking(operation, vc)) {
            return handleUserMethodCallNonBlocking(transformedArguments);
        } else {
            return handleUserMethodCallBlocking(transformedArguments, vc);
        }
    }

    @Override
    protected Uni> handleUserBatchLoad(DataFetchingEnvironment dfe, Object[] arguments) throws Exception {
        Context vc = Vertx.currentContext();
        if (runBlocking(dfe) || !BlockingHelper.nonBlockingShouldExecuteBlocking(operation, vc)) {
            return handleUserBatchLoadNonBlocking(arguments);
        } else {
            return handleUserBatchLoadBlocking(arguments, vc);
        }
    }

    private Uni handleUserMethodCallNonBlocking(final Object[] transformedArguments)
            throws Exception {
        return (Uni) operationInvoker.invoke(transformedArguments);
    }

    private Uni handleUserMethodCallBlocking(Object[] transformedArguments, Context vc)
            throws Exception {

        SmallRyeThreadContext threadContext = Arc.container().select(SmallRyeThreadContext.class).get();
        final Promise result = Promise.promise();

        // We need some make sure that we call given the context
        Callable contextualCallable = threadContext.contextualCallable(() -> {
            Object resultFromMethodCall = operationInvoker.invoke(transformedArguments);
            Uni uniFromMethodCall = (Uni) resultFromMethodCall;
            return uniFromMethodCall.subscribeAsCompletionStage().get();
        });

        // Here call blocking with context
        BlockingHelper.runBlocking(vc, contextualCallable, result);
        return Uni.createFrom().completionStage(result.future().toCompletionStage());
    }

    @SuppressWarnings("unchecked")
    protected Uni> handleUserBatchLoadNonBlocking(final Object[] arguments)
            throws Exception {
        return ((Uni>) operationInvoker.invoke(arguments));
    }

    private Uni> handleUserBatchLoadBlocking(Object[] arguments, Context vc)
            throws Exception {

        SmallRyeThreadContext threadContext = Arc.container().select(SmallRyeThreadContext.class).get();
        final Promise> result = Promise.promise();

        // We need some make sure that we call given the context
        Callable contextualCallable = threadContext.contextualCallable(() -> {
            Object resultFromMethodCall = operationInvoker.invoke(arguments);
            @SuppressWarnings("unchecked")
            Uni> uniFromMethodCall = (Uni>) resultFromMethodCall;
            return uniFromMethodCall.subscribeAsCompletionStage().get();
        });

        // Here call blocking with context
        BlockingHelper.runBlocking(vc, contextualCallable, result);
        return Uni.createFrom().completionStage(result.future().toCompletionStage());
    }

    private boolean runBlocking(DataFetchingEnvironment dfe) {
        return dfe.getGraphQlContext().get("runBlocking");
    }
}