Skip to content

Commit 9e31923

Browse files
committed
wip
1 parent 3f85c59 commit 9e31923

6 files changed

Lines changed: 289 additions & 13 deletions

File tree

src/main/java/graphql/execution/AsyncExecutionStrategy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ public AsyncExecutionStrategy(DataFetcherExceptionHandler exceptionHandler) {
3636
@Override
3737
@SuppressWarnings("FutureReturnValueIgnored")
3838
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
39-
4039
dataLoaderDispatcherStrategy.executionStrategy(executionContext, parameters);
4140

4241
Instrumentation instrumentation = executionContext.getInstrumentation();
@@ -60,14 +59,14 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
6059
for (FieldValueInfo completeValueInfo : completeValueInfos) {
6160
fieldValuesFutures.add(completeValueInfo.getFieldValueFuture());
6261
}
63-
dataLoaderDispatcherStrategy.executionStrategy_onFieldValuesInfo(completeValueInfos);
62+
dataLoaderDispatcherStrategy.executionStrategy_onFieldValuesInfo(completeValueInfos, parameters);
6463
executionStrategyCtx.onFieldValuesInfo(completeValueInfos);
6564
fieldValuesFutures.await().whenComplete(handleResultsConsumer);
6665
}).exceptionally((ex) -> {
6766
// if there are any issues with combining/handling the field results,
6867
// complete the future at all costs and bubble up any thrown exception so
6968
// the execution does not hang.
70-
dataLoaderDispatcherStrategy.executeObject_onFieldValuesException(ex);
69+
dataLoaderDispatcherStrategy.executeObject_onFieldValuesException(ex, parameters);
7170
executionStrategyCtx.onFieldValuesException();
7271
overallResult.completeExceptionally(ex);
7372
return null;

src/main/java/graphql/execution/DataLoaderDispatchStrategy.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,26 @@
22

33
import graphql.Internal;
44
import graphql.schema.DataFetcher;
5-
import graphql.schema.DataFetchingEnvironment;
65

76
import java.util.List;
87
import java.util.concurrent.CompletableFuture;
9-
import java.util.function.Supplier;
108

119
@Internal
1210
public interface DataLoaderDispatchStrategy {
1311

14-
public static final DataLoaderDispatchStrategy NO_OP = new DataLoaderDispatchStrategy() {
12+
DataLoaderDispatchStrategy NO_OP = new DataLoaderDispatchStrategy() {
1513
};
1614

1715

1816
default void executionStrategy(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
1917

2018
}
2119

22-
default void executionStrategy_onFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList) {
20+
default void executionStrategy_onFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList, ExecutionStrategyParameters parameters) {
2321

2422
}
2523

26-
default void executionStrategy_onFieldValuesException(Throwable t) {
24+
default void executionStrategy_onFieldValuesException(Throwable t, ExecutionStrategyParameters parameters) {
2725

2826
}
2927

@@ -32,21 +30,23 @@ default void executeObject(ExecutionContext executionContext, ExecutionStrategyP
3230

3331
}
3432

35-
default void executeObject_onFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList) {
33+
default void executeObject_onFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList, ExecutionStrategyParameters parameters) {
3634

3735
}
3836

39-
default void executeObject_onFieldValuesException(Throwable t) {
37+
default void executeObject_onFieldValuesException(Throwable t, ExecutionStrategyParameters parameters) {
4038

4139
}
4240

4341
default void fieldFetched(ExecutionContext executionContext,
44-
Supplier<DataFetchingEnvironment> dataFetchingEnvironment,
4542
ExecutionStrategyParameters executionStrategyParameters,
4643
DataFetcher<?> dataFetcher,
4744
CompletableFuture<Object> fetchedValue) {
4845

4946
}
5047

5148

49+
default DataFetcher<?> modifyDataFetcher(DataFetcher<?> dataFetcher) {
50+
return dataFetcher;
51+
}
5252
}

src/main/java/graphql/execution/Execution.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext exe
151151
CompletableFuture<ExecutionResult> result;
152152
try {
153153
ExecutionStrategy executionStrategy = executionContext.getStrategy(operation);
154+
executionStrategy.initBeforeExecution(executionContext);
154155
result = executionStrategy.execute(executionContext, parameters);
155156
} catch (NonNullableFieldWasNullException e) {
156157
// this means it was non-null types all the way from an offending non-null type

src/main/java/graphql/execution/ExecutionStrategy.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import graphql.execution.instrumentation.ExecuteObjectInstrumentationContext;
1818
import graphql.execution.instrumentation.Instrumentation;
1919
import graphql.execution.instrumentation.InstrumentationContext;
20+
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationState;
21+
import graphql.execution.instrumentation.dataloader.FallbackDataLoaderDispatchStrategy;
22+
import graphql.execution.instrumentation.dataloader.PerLevelDataLoaderDispatchStrategy;
2023
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
2124
import graphql.execution.instrumentation.parameters.InstrumentationFieldCompleteParameters;
2225
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
@@ -133,7 +136,7 @@ public abstract class ExecutionStrategy {
133136
protected final DataFetcherExceptionHandler dataFetcherExceptionHandler;
134137
private final ResolveType resolvedType = new ResolveType();
135138

136-
protected final DataLoaderDispatchStrategy dataLoaderDispatcherStrategy = DataLoaderDispatchStrategy.NO_OP;
139+
protected DataLoaderDispatchStrategy dataLoaderDispatcherStrategy;
137140

138141
/**
139142
* The default execution strategy constructor uses the {@link SimpleDataFetcherExceptionHandler}
@@ -143,6 +146,7 @@ protected ExecutionStrategy() {
143146
dataFetcherExceptionHandler = new SimpleDataFetcherExceptionHandler();
144147
}
145148

149+
146150
/**
147151
* The consumers of the execution strategy can pass in a {@link DataFetcherExceptionHandler} to better
148152
* decide what do when a data fetching error happens
@@ -153,6 +157,23 @@ protected ExecutionStrategy(DataFetcherExceptionHandler dataFetcherExceptionHand
153157
this.dataFetcherExceptionHandler = dataFetcherExceptionHandler;
154158
}
155159

160+
public void initBeforeExecution(ExecutionContext executionContext) {
161+
initDataLoaderStrategy(executionContext);
162+
}
163+
164+
private void initDataLoaderStrategy(ExecutionContext executionContext) {
165+
if (executionContext.getDataLoaderRegistry() == DataLoaderDispatcherInstrumentationState.EMPTY_DATALOADER_REGISTRY) {
166+
this.dataLoaderDispatcherStrategy = DataLoaderDispatchStrategy.NO_OP;
167+
return;
168+
}
169+
if (this instanceof AsyncExecutionStrategy) {
170+
this.dataLoaderDispatcherStrategy = new PerLevelDataLoaderDispatchStrategy(executionContext);
171+
} else {
172+
this.dataLoaderDispatcherStrategy = new FallbackDataLoaderDispatchStrategy(executionContext);
173+
}
174+
}
175+
176+
156177
@Internal
157178
public static String mkNameForPath(Field currentField) {
158179
return mkNameForPath(Collections.singletonList(currentField));
@@ -188,6 +209,7 @@ public static String mkNameForPath(List<Field> currentField) {
188209
* @throws NonNullableFieldWasNullException in the future if a non-null field resolves to a null value
189210
*/
190211
protected CompletableFuture<Map<String, Object>> executeObject(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
212+
dataLoaderDispatcherStrategy.executeObject(executionContext, parameters);
191213
Instrumentation instrumentation = executionContext.getInstrumentation();
192214
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
193215

@@ -211,12 +233,14 @@ protected CompletableFuture<Map<String, Object>> executeObject(ExecutionContext
211233
for (FieldValueInfo completeValueInfo : completeValueInfos) {
212234
resultFutures.add(completeValueInfo.getFieldValueFuture());
213235
}
236+
dataLoaderDispatcherStrategy.executeObject_onFieldValuesInfo(completeValueInfos, parameters);
214237
resolveObjectCtx.onFieldValuesInfo(completeValueInfos);
215238
resultFutures.await().whenComplete(handleResultsConsumer);
216239
}).exceptionally((ex) -> {
217240
// if there are any issues with combining/handling the field results,
218241
// complete the future at all costs and bubble up any thrown exception so
219242
// the execution does not hang.
243+
dataLoaderDispatcherStrategy.executeObject_onFieldValuesException(ex, parameters);
220244
resolveObjectCtx.onFieldValuesException();
221245
overallResult.completeExceptionally(ex);
222246
return null;
@@ -371,9 +395,10 @@ protected CompletableFuture<FetchedValue> fetchField(ExecutionContext executionC
371395
executionContext.getInstrumentationState())
372396
);
373397

398+
dataFetcher = dataLoaderDispatcherStrategy.modifyDataFetcher(dataFetcher);
374399
dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams, executionContext.getInstrumentationState());
375400
CompletableFuture<Object> fetchedValue = invokeDataFetcher(executionContext, parameters, fieldDef, dataFetchingEnvironment, dataFetcher);
376-
401+
dataLoaderDispatcherStrategy.fieldFetched(executionContext, parameters, dataFetcher, fetchedValue);
377402
fetchCtx.onDispatched(fetchedValue);
378403
return fetchedValue
379404
.handle((result, exception) -> {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package graphql.execution.instrumentation.dataloader;
2+
3+
import graphql.Internal;
4+
import graphql.execution.DataLoaderDispatchStrategy;
5+
import graphql.execution.ExecutionContext;
6+
import graphql.schema.DataFetcher;
7+
8+
9+
/**
10+
* Used when the execution strategy is not an AsyncExecutionStrategy: simply dispatch always after each DF.
11+
*/
12+
@Internal
13+
public class FallbackDataLoaderDispatchStrategy implements DataLoaderDispatchStrategy {
14+
15+
private final ExecutionContext executionContext;
16+
17+
public FallbackDataLoaderDispatchStrategy(ExecutionContext executionContext) {
18+
this.executionContext = executionContext;
19+
}
20+
21+
22+
@Override
23+
public DataFetcher<?> modifyDataFetcher(DataFetcher<?> dataFetcher) {
24+
return (DataFetcher<Object>) environment -> {
25+
Object obj = dataFetcher.get(environment);
26+
executionContext.getDataLoaderRegistry().dispatchAll();
27+
return obj;
28+
};
29+
30+
}
31+
}

0 commit comments

Comments
 (0)