JS like Batching by andimarek · Pull Request #3873 · graphql-java/graphql-java · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/graphql/execution/AsyncExecutionStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public AsyncExecutionStrategy(DataFetcherExceptionHandler exceptionHandler) {
@Override
@SuppressWarnings("FutureReturnValueIgnored")
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
executionContext.running();
DataLoaderDispatchStrategy dataLoaderDispatcherStrategy = executionContext.getDataLoaderDispatcherStrategy();
dataLoaderDispatcherStrategy.executionStrategy(executionContext, parameters);
Instrumentation instrumentation = executionContext.getInstrumentation();
Expand All @@ -50,6 +51,7 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont

Optional<ExecutionResult> isNotSensible = Introspection.isIntrospectionSensible(fields, executionContext);
if (isNotSensible.isPresent()) {
executionContext.finished();
return CompletableFuture.completedFuture(isNotSensible.get());
}

Expand All @@ -60,11 +62,13 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
executionStrategyCtx.onDispatched();

futures.await().whenComplete((completeValueInfos, throwable) -> {
executionContext.running();
List<String> fieldsExecutedOnInitialResult = deferredExecutionSupport.getNonDeferredFieldNames(fieldNames);

BiConsumer<List<Object>, Throwable> handleResultsConsumer = handleResults(executionContext, fieldsExecutedOnInitialResult, overallResult);
if (throwable != null) {
handleResultsConsumer.accept(null, throwable.getCause());
executionContext.finished();
return;
}

Expand All @@ -75,17 +79,21 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(completeValueInfos);
executionStrategyCtx.onFieldValuesInfo(completeValueInfos);
fieldValuesFutures.await().whenComplete(handleResultsConsumer);
executionContext.finished();
}).exceptionally((ex) -> {
executionContext.running();
// if there are any issues with combining/handling the field results,
// complete the future at all costs and bubble up any thrown exception so
// the execution does not hang.
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesException(ex);
executionStrategyCtx.onFieldValuesException();
overallResult.completeExceptionally(ex);
executionContext.finished();
return null;
});

overallResult.whenComplete(executionStrategyCtx::onCompleted);
executionContext.finished();
return overallResult;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import graphql.Internal;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;

import java.util.List;
import java.util.function.Supplier;

@Internal
public interface DataLoaderDispatchStrategy {
Expand Down Expand Up @@ -44,7 +46,7 @@ default void executeObjectOnFieldValuesException(Throwable t, ExecutionStrategyP
default void fieldFetched(ExecutionContext executionContext,
ExecutionStrategyParameters executionStrategyParameters,
DataFetcher<?> dataFetcher,
Object fetchedValue) {
Object fetchedValue, Supplier<DataFetchingEnvironment> dataFetchingEnvironment) {

}

Expand Down
6 changes: 5 additions & 1 deletion src/main/java/graphql/execution/Execution.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import graphql.schema.impl.SchemaUtil;
import org.jspecify.annotations.NonNull;
import graphql.util.FpKit;
import org.jspecify.annotations.NonNull;
import org.reactivestreams.Publisher;

import java.util.Collections;
Expand Down Expand Up @@ -58,6 +58,8 @@ public class Execution {
private final ValueUnboxer valueUnboxer;
private final boolean doNotAutomaticallyDispatchDataLoader;

public static final String EXECUTION_CONTEXT_KEY = "__GraphQL_Java_ExecutionContext";

public Execution(ExecutionStrategy queryStrategy,
ExecutionStrategy mutationStrategy,
ExecutionStrategy subscriptionStrategy,
Expand Down Expand Up @@ -114,6 +116,8 @@ public CompletableFuture<ExecutionResult> execute(Document document, GraphQLSche
.build();

executionContext.getGraphQLContext().put(ResultNodesInfo.RESULT_NODES_INFO, executionContext.getResultNodesInfo());
executionContext.getGraphQLContext().put(EXECUTION_CONTEXT_KEY, executionContext);


InstrumentationExecutionParameters parameters = new InstrumentationExecutionParameters(
executionInput, graphQLSchema
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/graphql/execution/ExecutionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
Expand Down Expand Up @@ -63,6 +64,8 @@ public class ExecutionContext {
private final Supplier<ExecutableNormalizedOperation> queryTree;
private final boolean propagateErrorsOnNonNullContractFailure;

private final AtomicInteger isRunning = new AtomicInteger(0);

// this is modified after creation so it needs to be volatile to ensure visibility across Threads
private volatile DataLoaderDispatchStrategy dataLoaderDispatcherStrategy = DataLoaderDispatchStrategy.NO_OP;

Expand Down Expand Up @@ -349,4 +352,16 @@ public ExecutionContext transform(Consumer<ExecutionContextBuilder> builderConsu
public ResultNodesInfo getResultNodesInfo() {
return resultNodesInfo;
}

public boolean isRunning() {
return isRunning.get() > 0;
}

public void running() {
isRunning.incrementAndGet();
}

public void finished() {
isRunning.decrementAndGet();
}
}
27 changes: 24 additions & 3 deletions src/main/java/graphql/execution/ExecutionStrategy.java
Loading