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

graphql.nadel.engine.execution.Execution Maven / Gradle / Ivy

Go to download

Nadel is a Java library that combines multiple GrahpQL services together into one API.

The newest version!
package graphql.nadel.engine.execution;

import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.GraphQLError;
import graphql.Internal;
import graphql.execution.ExecutionContext;
import graphql.execution.ExecutionId;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.InstrumentationState;
import graphql.execution.nextgen.ExecutionHelper;
import graphql.execution.nextgen.FieldSubSelection;
import graphql.language.Document;
import graphql.nadel.NadelExecutionParams;
import graphql.nadel.Service;
import graphql.nadel.engine.BenchmarkContext;
import graphql.nadel.engine.FieldInfos;
import graphql.nadel.engine.NadelContext;
import graphql.nadel.engine.instrumentation.NadelEngineInstrumentation;
import graphql.nadel.engine.result.ResultComplexityAggregator;
import graphql.nadel.engine.result.ResultNodesUtil;
import graphql.nadel.engine.result.RootExecutionResultNode;
import graphql.nadel.hooks.ServiceExecutionHooks;
import graphql.nadel.instrumentation.NadelInstrumentation;
import graphql.nadel.instrumentation.parameters.NadelInstrumentRootExecutionResultParameters;
import graphql.nadel.instrumentation.parameters.NadelInstrumentationExecuteOperationParameters;
import graphql.nadel.introspection.IntrospectionRunner;
import graphql.nadel.normalized.NormalizedQueryFactory;
import graphql.nadel.normalized.NormalizedQueryFromAst;
import graphql.schema.GraphQLSchema;

import java.util.List;
import java.util.concurrent.CompletableFuture;

import static java.util.concurrent.CompletableFuture.completedFuture;

@Internal
public class Execution {

    private final GraphQLSchema overallSchema;
    private final NadelInstrumentation instrumentation;
    private final IntrospectionRunner introspectionRunner;
    private final NadelExecutionStrategy nadelExecutionStrategy;

    private final ExecutionHelper executionHelper = new ExecutionHelper();
    private final NormalizedQueryFactory normalizedQueryFactory = new NormalizedQueryFactory();

    public Execution(List services,
                     GraphQLSchema overallSchema,
                     NadelInstrumentation instrumentation,
                     IntrospectionRunner introspectionRunner,
                     ServiceExecutionHooks serviceExecutionHooks,
                     Object userSuppliedContext) {
        this.overallSchema = overallSchema;
        this.instrumentation = instrumentation;
        this.introspectionRunner = introspectionRunner;
        FieldInfos fieldsInfos = FieldInfos.createFieldsInfos(overallSchema, services);
        if (userSuppliedContext instanceof BenchmarkContext) {
            BenchmarkContext.NadelExecutionStrategyArgs args = ((BenchmarkContext) userSuppliedContext).nadelExecutionStrategyArgs;
            args.services = services;
            args.fieldInfos = fieldsInfos;
            args.overallSchema = overallSchema;
            args.instrumentation = instrumentation;
            args.serviceExecutionHooks = serviceExecutionHooks;
        }

        this.nadelExecutionStrategy = new NadelExecutionStrategy(services, fieldsInfos, overallSchema, instrumentation, serviceExecutionHooks);
    }

    public CompletableFuture execute(ExecutionInput executionInput,
                                                      Document document,
                                                      ExecutionId executionId,
                                                      InstrumentationState instrumentationState,
                                                      NadelExecutionParams nadelExecutionParams) {

        NormalizedQueryFromAst normalizedQueryFromAst = normalizedQueryFactory.createNormalizedQuery(overallSchema, document, executionInput.getOperationName(), executionInput.getVariables());

        NadelContext nadelContext = NadelContext.newContext()
                .userSuppliedContext(executionInput.getContext())
                .originalOperationName(document, executionInput.getOperationName())
                .artificialFieldsUUID(nadelExecutionParams.getArtificialFieldsUUID())
                .normalizedOverallQuery(normalizedQueryFromAst)
                .nadelExecutionHints(nadelExecutionParams.getNadelExecutionHints())
                .build();

        executionInput = executionInput.transform(builder -> builder.context(nadelContext));

        ExecutionHelper.ExecutionData executionData;
        try {
            executionData = executionHelper.createExecutionData(document, overallSchema, executionId, executionInput, instrumentationState);
        } catch (RuntimeException rte) {
            //
            // this is the same behavior as in graphql-java
            if (rte instanceof GraphQLError) {
                return completedFuture(new ExecutionResultImpl((GraphQLError) rte));
            }
            throw rte;
        }

        ExecutionContext executionContext = executionData.executionContext;
        FieldSubSelection fieldSubSelection = executionHelper.getFieldSubSelection(executionContext);

        NadelInstrumentationExecuteOperationParameters executeOperationParameters = buildInstrumentationParameters(instrumentationState, normalizedQueryFromAst, executionContext);
        CompletableFuture> instrumentationCtxFuture = instrumentation.beginExecute(executeOperationParameters);

        ExecutionInput finalExecutionInput = executionInput;

        return instrumentationCtxFuture.thenCompose(instrumentationCtx -> {

            CompletableFuture result;
            ResultComplexityAggregator resultComplexityAggregator = new ResultComplexityAggregator();
            if (introspectionRunner.isIntrospectionQuery(executionContext, fieldSubSelection)) {
                result = introspectionRunner.runIntrospection(executionContext, fieldSubSelection, finalExecutionInput);
            } else {
                if (nadelContext.getUserSuppliedContext() instanceof BenchmarkContext) {
                    BenchmarkContext.NadelExecutionStrategyArgs args = ((BenchmarkContext) nadelContext.getUserSuppliedContext()).nadelExecutionStrategyArgs;
                    args.executionContext = executionContext;
                    args.fieldSubSelection = fieldSubSelection;
                    args.resultComplexityAggregator = resultComplexityAggregator;
                }
                CompletableFuture resultNodes = nadelExecutionStrategy.execute(executionContext, fieldSubSelection, resultComplexityAggregator);
                result = resultNodes.thenApply(rootResultNode -> {
                    if (nadelContext.getUserSuppliedContext() instanceof BenchmarkContext) {
                        ((BenchmarkContext) nadelContext.getUserSuppliedContext()).overallResult = rootResultNode;
                    }
                    if (instrumentation instanceof NadelEngineInstrumentation) {
                        rootResultNode = ((NadelEngineInstrumentation) instrumentation).instrumentRootExecutionResult(rootResultNode, new NadelInstrumentRootExecutionResultParameters(executionContext, normalizedQueryFromAst, instrumentationState));
                    }
                    return withNodeComplexity(ResultNodesUtil.toExecutionResult(rootResultNode), resultComplexityAggregator);
                });
            }

            // note this happens NOW - not when the result completes
            instrumentationCtx.onDispatched(result);
            result = result.whenComplete(instrumentationCtx::onCompleted);
            return result;
        });
    }

    private static NadelInstrumentationExecuteOperationParameters buildInstrumentationParameters(
            InstrumentationState instrumentationState, NormalizedQueryFromAst normalizedQueryFromAst, ExecutionContext executionContext
    ) {
        return new NadelInstrumentationExecuteOperationParameters(
                normalizedQueryFromAst,
                executionContext.getDocument(),
                executionContext.getGraphQLSchema(),
                executionContext.getVariables(),
                executionContext.getOperationDefinition(),
                instrumentationState,
                executionContext.getContext());
    }

    public ExecutionResult withNodeComplexity(ExecutionResult executionResult, ResultComplexityAggregator resultComplexityAggregator) {
        return ExecutionResultImpl.newExecutionResult().from(executionResult)
                .addExtension("resultComplexity", resultComplexityAggregator.snapshotResultComplexityData())
                .build();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy