FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

make dataloader work inside defer blocks by andimarek · Pull Request #3980 · graphql-java/graphql-java · GitHub

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public AsyncExecutionStrategy(DataFetcherExceptionHandler exceptionHandler) {
@SuppressWarnings("FutureReturnValueIgnored")
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
DataLoaderDispatchStrategy dataLoaderDispatcherStrategy = executionContext.getDataLoaderDispatcherStrategy();
dataLoaderDispatcherStrategy.executionStrategy(executionContext, parameters);
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);

Expand All @@ -54,6 +53,9 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
}

DeferredExecutionSupport deferredExecutionSupport = createDeferredExecutionSupport(executionContext, parameters);

dataLoaderDispatcherStrategy.executionStrategy(executionContext, parameters, deferredExecutionSupport.getNonDeferredFieldNames(fieldNames).size());

Async.CombinedBuilder<FieldValueInfo> futures = getAsyncFieldValueInfo(executionContext, parameters, deferredExecutionSupport);

CompletableFuture<ExecutionResult> overallResult = new CompletableFuture<>();
Expand All @@ -72,14 +74,14 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
for (FieldValueInfo completeValueInfo : completeValueInfos) {
fieldValuesFutures.addObject(completeValueInfo.getFieldValueObject());
}
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(completeValueInfos);
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(completeValueInfos, parameters);
executionStrategyCtx.onFieldValuesInfo(completeValueInfos);
fieldValuesFutures.await().whenComplete(handleResultsConsumer);
}).exceptionally((ex) -> {
// 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);
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesException(ex, parameters);
executionStrategyCtx.onFieldValuesException();
overallResult.completeExceptionally(ex);
return null;
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ private Object resolveSerialField(ExecutionContext executionContext,
if (fieldWithInfo instanceof CompletableFuture) {
//noinspection unchecked
return ((CompletableFuture<FieldValueInfo>) fieldWithInfo).thenCompose(fvi -> {
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(List.of(fvi));
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(List.of(fvi), newParameters);
CompletableFuture<Object> fieldValueFuture = fvi.getFieldValueFuture();
return fieldValueFuture;
});
} else {
FieldValueInfo fvi = (FieldValueInfo) fieldWithInfo;
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(List.of(fvi));
dataLoaderDispatcherStrategy.executionStrategyOnFieldValuesInfo(List.of(fvi), newParameters);
return fvi.getFieldValueObject();
}
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,35 @@ public interface DataLoaderDispatchStrategy {
};


default void executionStrategy(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
default void executionStrategy(ExecutionContext executionContext, ExecutionStrategyParameters parameters, int fieldCount) {

}

default void executionSerialStrategy(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {

}

default void executionStrategyOnFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList) {
default void executionStrategyOnFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList, ExecutionStrategyParameters parameters) {

}

default void executionStrategyOnFieldValuesException(Throwable t) {
default void executionStrategyOnFieldValuesException(Throwable t, ExecutionStrategyParameters parameters) {

}


default void executeObject(ExecutionContext executionContext, ExecutionStrategyParameters executionStrategyParameters) {
default void executeObject(ExecutionContext executionContext, ExecutionStrategyParameters executionStrategyParameters, int fieldCount) {

}

default void executeObjectOnFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList, ExecutionStrategyParameters parameters) {

}

default void deferredOnFieldValue(String resultKey, FieldValueInfo fieldValueInfo, Throwable throwable, ExecutionStrategyParameters parameters) {

}

default void executeObjectOnFieldValuesException(Throwable t, ExecutionStrategyParameters parameters) {

}
Expand All @@ -55,8 +59,4 @@ default void fieldFetched(ExecutionContext executionContext,
default DataFetcher<?> modifyDataFetcher(DataFetcher<?> dataFetcher) {
return dataFetcher;
}

default void executeDeferredOnFieldValueInfo(FieldValueInfo fieldValueInfo, ExecutionStrategyParameters executionStrategyParameters) {

}
}
10 changes: 1 addition & 9 deletions src/main/java/graphql/execution/Execution.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.ExperimentalApi;
import graphql.GraphQLContext;
import graphql.GraphQLError;
import graphql.Internal;
Expand All @@ -16,7 +15,6 @@
import graphql.execution.instrumentation.InstrumentationState;
import graphql.execution.instrumentation.dataloader.FallbackDataLoaderDispatchStrategy;
import graphql.execution.instrumentation.dataloader.PerLevelDataLoaderDispatchStrategy;
import graphql.execution.instrumentation.dataloader.PerLevelDataLoaderDispatchStrategyWithDeferAlwaysDispatch;
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import graphql.extensions.ExtensionsBuilder;
Expand All @@ -37,7 +35,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

Expand Down Expand Up @@ -258,12 +255,7 @@ private DataLoaderDispatchStrategy createDataLoaderDispatchStrategy(ExecutionCon
return DataLoaderDispatchStrategy.NO_OP;
}
if (!executionContext.isSubscriptionOperation()) {
boolean deferEnabled = executionContext.hasIncrementalSupport();

// Dedicated strategy for defer support, for safety purposes.
return deferEnabled ?
new PerLevelDataLoaderDispatchStrategyWithDeferAlwaysDispatch(executionContext) :
new PerLevelDataLoaderDispatchStrategy(executionContext);
return new PerLevelDataLoaderDispatchStrategy(executionContext);
} else {
return new FallbackDataLoaderDispatchStrategy(executionContext);
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import graphql.EngineRunningState;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.ExperimentalApi;
import graphql.GraphQLError;
import graphql.Internal;
import graphql.PublicSpi;
Expand Down Expand Up @@ -50,7 +49,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
Expand Down Expand Up @@ -197,7 +195,6 @@ public static String mkNameForPath(List<Field> currentField) {
@DuckTyped(shape = "CompletableFuture<Map<String, Object>> | Map<String, Object>")
protected Object executeObject(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
DataLoaderDispatchStrategy dataLoaderDispatcherStrategy = executionContext.getDataLoaderDispatcherStrategy();
dataLoaderDispatcherStrategy.executeObject(executionContext, parameters);
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);

Expand All @@ -212,6 +209,7 @@ protected Object executeObject(ExecutionContext executionContext, ExecutionStrat

CompletableFuture<Map<String, Object>> overallResult = new CompletableFuture<>();
List<String> fieldsExecutedOnInitialResult = deferredExecutionSupport.getNonDeferredFieldNames(fieldNames);
dataLoaderDispatcherStrategy.executeObject(executionContext, parameters, fieldsExecutedOnInitialResult.size());
BiConsumer<List<Object>, Throwable> handleResultsConsumer = buildFieldValueMap(fieldsExecutedOnInitialResult, overallResult, executionContext);

resolveObjectCtx.onDispatched();
Expand Down Expand Up @@ -300,7 +298,7 @@ DeferredExecutionSupport createDeferredExecutionSupport(ExecutionContext executi
) {
MergedSelectionSet fields = parameters.getFields();

executionContext.getIncrementalCallState().enqueue(deferredExecutionSupport.createCalls(parameters));
executionContext.getIncrementalCallState().enqueue(deferredExecutionSupport.createCalls());

// Only non-deferred fields should be considered for calculating the expected size of futures.
Async.CombinedBuilder<FieldValueInfo> futures = Async
Expand Down Expand Up @@ -400,7 +398,6 @@ private Object fetchField(GraphQLFieldDefinition fieldDef, ExecutionContext exec
}

MergedField field = parameters.getField();
String pathString = parameters.getPath().toString();
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();

// if the DF (like PropertyDataFetcher) does not use the arguments or execution step info then dont build any
Expand Down Expand Up @@ -435,6 +432,7 @@ private Object fetchField(GraphQLFieldDefinition fieldDef, ExecutionContext exec
.parentType(parentType)
.selectionSet(fieldCollector)
.queryDirectives(queryDirectives)
.deferredCallContext(parameters.getDeferredCallContext())
.build();
});

Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public ExecutionStrategyParameters getParent() {
* @return the deferred call context or null if we're not in the scope of a deferred call
*/
@Nullable
@Internal
public DeferredCallContext getDeferredCallContext() {
return deferredCallContext;
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import graphql.GraphQLError;
import graphql.Internal;
import graphql.VisibleForTesting;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
Expand All @@ -18,8 +19,31 @@
@Internal
public class DeferredCallContext {

private final int startLevel;
private final int fields;

private final List<GraphQLError> errors = new CopyOnWriteArrayList<>();

public DeferredCallContext(int startLevel, int fields) {
this.startLevel = startLevel;
this.fields = fields;
}

@VisibleForTesting
public DeferredCallContext() {
this.startLevel = 0;
this.fields = 0;
}

public int getStartLevel() {
return startLevel;
}

public int getFields() {
return fields;
}


public void addErrors(List<GraphQLError> errors) {
this.errors.addAll(errors);
}
Expand All @@ -34,4 +58,6 @@ public void addError(GraphQLError graphqlError) {
public List<GraphQLError> getErrors() {
return errors;
}


}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public interface DeferredExecutionSupport {

List<String> getNonDeferredFieldNames(List<String> allFieldNames);

Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters);
Set<IncrementalCall<? extends IncrementalPayload>> createCalls();

DeferredExecutionSupport NOOP = new DeferredExecutionSupport.NoOp();

Expand Down Expand Up @@ -106,23 +106,24 @@ public List<String> getNonDeferredFieldNames(List<String> allFieldNames) {
}

@Override
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters) {
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls() {
ImmutableSet<DeferredExecution> deferredExecutions = deferredExecutionToFields.keySet();
Set<IncrementalCall<? extends IncrementalPayload>> set = new HashSet<>(deferredExecutions.size());
for (DeferredExecution deferredExecution : deferredExecutions) {
set.add(this.createDeferredFragmentCall(deferredExecution, executionStrategyParameters));
set.add(this.createDeferredFragmentCall(deferredExecution));
}
return set;
}

private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferredExecution, ExecutionStrategyParameters executionStrategyParameters) {
DeferredCallContext deferredCallContext = new DeferredCallContext();
private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferredExecution) {
int level = parameters.getPath().getLevel() + 1;
DeferredCallContext deferredCallContext = new DeferredCallContext(level, deferredFields.size());

List<MergedField> mergedFields = deferredExecutionToFields.get(deferredExecution);

List<Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>>> calls = FpKit.arrayListSizedTo(mergedFields);
for (MergedField currentField : mergedFields) {
calls.add(this.createResultSupplier(currentField, deferredCallContext, executionStrategyParameters));
calls.add(this.createResultSupplier(currentField, deferredCallContext));
}

return new DeferredFragmentCall(
Expand All @@ -135,13 +136,12 @@ private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferr

private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>> createResultSupplier(
MergedField currentField,
DeferredCallContext deferredCallContext,
ExecutionStrategyParameters executionStrategyParameters
DeferredCallContext deferredCallContext
) {
Map<String, MergedField> fields = new LinkedHashMap<>();
fields.put(currentField.getResultKey(), currentField);

ExecutionStrategyParameters callParameters = parameters.transform(builder ->
ExecutionStrategyParameters executionStrategyParameters = parameters.transform(builder ->
{
MergedSelectionSet mergedSelectionSet = MergedSelectionSet.newMergedSelectionSet().subFields(fields).build();
ResultPath path = parameters.getPath().segment(currentField.getResultKey());
Expand All @@ -158,22 +158,23 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult

instrumentation.beginDeferredField(executionContext.getInstrumentationState());

// todo: handle cached computations
return dfCache.computeIfAbsent(
currentField.getResultKey(),
// The same field can be associated with multiple defer executions, so
// we memoize the field resolution to avoid multiple calls to the same data fetcher
key -> FpKit.interThreadMemoize(() -> {
CompletableFuture<FieldValueInfo> fieldValueResult = resolveFieldWithInfoFn
.apply(executionContext, callParameters);
CompletableFuture<FieldValueInfo> fieldValueResult = resolveFieldWithInfoFn.apply(executionContext, executionStrategyParameters);
Comment thread
andimarek marked this conversation as resolved.

fieldValueResult.whenComplete((fieldValueInfo, throwable) -> {
executionContext.getDataLoaderDispatcherStrategy().deferredOnFieldValue(currentField.getResultKey(), fieldValueInfo, throwable, executionStrategyParameters);
});

CompletableFuture<ExecutionResult> executionResultCF = fieldValueResult
.thenCompose(fvi -> {
executionContext.getDataLoaderDispatcherStrategy().executeDeferredOnFieldValueInfo(fvi, executionStrategyParameters);

return fvi
.getFieldValueFuture()
.thenApply(fv -> ExecutionResultImpl.newExecutionResult().data(fv).build());
}
CompletableFuture<ExecutionResult> executionResultCF = fieldValueResult
.thenCompose(fvi -> fvi
.getFieldValueFuture()
.thenApply(fv -> ExecutionResultImpl.newExecutionResult().data(fv).build())
);

return executionResultCF
Expand Down Expand Up @@ -207,7 +208,7 @@ public List<String> getNonDeferredFieldNames(List<String> allFieldNames) {
}

@Override
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters) {
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls() {
return Collections.emptySet();
}
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,5 @@ private Supplier<SingleSubscriberPublisher<DelayedIncrementalPartialResult>> cre
public Publisher<DelayedIncrementalPartialResult> startDeferredCalls() {
return publisher.get();
}

}
Loading

Back | FazBrowse Home | New Git URL