Skip to content

Commit fde25db

Browse files
authored
Merge pull request graphql-java#3639 from felipe-gdr/defer-dataloader-integration
Defer dataloader integration
2 parents 435de80 + 3fc8444 commit fde25db

12 files changed

+750
-337
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import graphql.schema.DataFetcher;
55

66
import java.util.List;
7-
import java.util.concurrent.CompletableFuture;
87

98
@Internal
109
public interface DataLoaderDispatchStrategy {
@@ -50,7 +49,7 @@ default DataFetcher<?> modifyDataFetcher(DataFetcher<?> dataFetcher) {
5049
return dataFetcher;
5150
}
5251

53-
default void deferredField(ExecutionContext executionContext, MergedField currentField) {
52+
default void executeDeferredOnFieldValueInfo(FieldValueInfo fieldValueInfo, ExecutionStrategyParameters executionStrategyParameters) {
5453

5554
}
5655
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import graphql.execution.instrumentation.InstrumentationState;
1515
import graphql.execution.instrumentation.dataloader.FallbackDataLoaderDispatchStrategy;
1616
import graphql.execution.instrumentation.dataloader.PerLevelDataLoaderDispatchStrategy;
17+
import graphql.execution.instrumentation.dataloader.PerLevelDataLoaderDispatchStrategyWithDeferAlwaysDispatch;
1718
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
1819
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
1920
import graphql.extensions.ExtensionsBuilder;
@@ -228,7 +229,14 @@ private DataLoaderDispatchStrategy createDataLoaderDispatchStrategy(ExecutionCon
228229
return DataLoaderDispatchStrategy.NO_OP;
229230
}
230231
if (executionStrategy instanceof AsyncExecutionStrategy) {
231-
return new PerLevelDataLoaderDispatchStrategy(executionContext);
232+
boolean deferEnabled = Optional.ofNullable(executionContext.getGraphQLContext())
233+
.map(graphqlContext -> graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT))
234+
.orElse(false);
235+
236+
// Dedicated strategy for defer support, for safety purposes.
237+
return deferEnabled ?
238+
new PerLevelDataLoaderDispatchStrategyWithDeferAlwaysDispatch(executionContext) :
239+
new PerLevelDataLoaderDispatchStrategy(executionContext);
232240
} else {
233241
return new FallbackDataLoaderDispatchStrategy(executionContext);
234242
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ Async.CombinedBuilder<FieldValueInfo> getAsyncFieldValueInfo(
318318
) {
319319
MergedSelectionSet fields = parameters.getFields();
320320

321-
executionContext.getIncrementalCallState().enqueue(deferredExecutionSupport.createCalls());
321+
executionContext.getIncrementalCallState().enqueue(deferredExecutionSupport.createCalls(parameters));
322322

323323
// Only non-deferred fields should be considered for calculating the expected size of futures.
324324
Async.CombinedBuilder<FieldValueInfo> futures = Async

src/main/java/graphql/execution/incremental/DeferredExecutionSupport.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public interface DeferredExecutionSupport {
4444

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

47-
Set<IncrementalCall<? extends IncrementalPayload>> createCalls();
47+
Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters);
4848

4949
DeferredExecutionSupport NOOP = new DeferredExecutionSupport.NoOp();
5050

@@ -105,19 +105,19 @@ public List<String> getNonDeferredFieldNames(List<String> allFieldNames) {
105105
}
106106

107107
@Override
108-
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls() {
108+
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters) {
109109
return deferredExecutionToFields.keySet().stream()
110-
.map(this::createDeferredFragmentCall)
110+
.map(deferredExecution -> this.createDeferredFragmentCall(deferredExecution, executionStrategyParameters))
111111
.collect(Collectors.toSet());
112112
}
113113

114-
private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferredExecution) {
114+
private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferredExecution, ExecutionStrategyParameters executionStrategyParameters) {
115115
DeferredCallContext deferredCallContext = new DeferredCallContext();
116116

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

119119
List<Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>>> calls = mergedFields.stream()
120-
.map(currentField -> this.createResultSupplier(currentField, deferredCallContext))
120+
.map(currentField -> this.createResultSupplier(currentField, deferredCallContext, executionStrategyParameters))
121121
.collect(Collectors.toList());
122122

123123
return new DeferredFragmentCall(
@@ -130,7 +130,8 @@ private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferr
130130

131131
private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>> createResultSupplier(
132132
MergedField currentField,
133-
DeferredCallContext deferredCallContext
133+
DeferredCallContext deferredCallContext,
134+
ExecutionStrategyParameters executionStrategyParameters
134135
) {
135136
Map<String, MergedField> fields = new LinkedHashMap<>();
136137
fields.put(currentField.getResultKey(), currentField);
@@ -149,7 +150,6 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult
149150

150151
Instrumentation instrumentation = executionContext.getInstrumentation();
151152

152-
executionContext.getDataLoaderDispatcherStrategy().deferredField(executionContext, currentField);
153153
instrumentation.beginDeferredField(executionContext.getInstrumentationState());
154154

155155
return dfCache.computeIfAbsent(
@@ -160,12 +160,14 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult
160160
CompletableFuture<FieldValueInfo> fieldValueResult = resolveFieldWithInfoFn
161161
.apply(executionContext, callParameters);
162162

163-
// Create a reference to the CompletableFuture that resolves an ExecutionResult
164-
// so we can pass it to the Instrumentation "onDispatched" callback.
165163
CompletableFuture<ExecutionResult> executionResultCF = fieldValueResult
166-
.thenCompose(fvi -> fvi
167-
.getFieldValueFuture()
168-
.thenApply(fv -> ExecutionResultImpl.newExecutionResult().data(fv).build())
164+
.thenCompose(fvi -> {
165+
executionContext.getDataLoaderDispatcherStrategy().executeDeferredOnFieldValueInfo(fvi, executionStrategyParameters);
166+
167+
return fvi
168+
.getFieldValueFuture()
169+
.thenApply(fv -> ExecutionResultImpl.newExecutionResult().data(fv).build());
170+
}
169171
);
170172

171173
return executionResultCF
@@ -199,7 +201,7 @@ public List<String> getNonDeferredFieldNames(List<String> allFieldNames) {
199201
}
200202

201203
@Override
202-
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls() {
204+
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters) {
203205
return Collections.emptySet();
204206
}
205207
}

src/main/java/graphql/execution/instrumentation/dataloader/DataLoaderDispatcherInstrumentation.java

Whitespace-only changes.

src/main/java/graphql/execution/instrumentation/dataloader/PerLevelDataLoaderDispatchStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public PerLevelDataLoaderDispatchStrategy(ExecutionContext executionContext) {
9898
}
9999

100100
@Override
101-
public void deferredField(ExecutionContext executionContext, MergedField currentField) {
101+
public void executeDeferredOnFieldValueInfo(FieldValueInfo fieldValueInfo, ExecutionStrategyParameters executionStrategyParameters) {
102102
throw new UnsupportedOperationException("Data Loaders cannot be used to resolve deferred fields");
103103
}
104104

0 commit comments

Comments
 (0)