Skip to content

Instantly share code, notes, and snippets.

@bbakerman
Created March 20, 2018 07:06
Show Gist options
  • Save bbakerman/b358e2e6a209283775c998116abdd309 to your computer and use it in GitHub Desktop.
Save bbakerman/b358e2e6a209283775c998116abdd309 to your computer and use it in GitHub Desktop.
Index: src/main/java/graphql/execution/instrumentation/dataloader/DataLoaderDispatcherInstrumentation.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/graphql/execution/instrumentation/dataloader/DataLoaderDispatcherInstrumentation.java (date 1521428082000)
+++ src/main/java/graphql/execution/instrumentation/dataloader/DataLoaderDispatcherInstrumentation.java (revision )
@@ -23,9 +23,12 @@
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
+import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
import static graphql.execution.instrumentation.SimpleInstrumentationContext.whenDispatched;
@@ -76,6 +79,7 @@
private static class CallStack implements InstrumentationState {
private boolean aggressivelyBatching = true;
private final Deque<Boolean> stack = new ArrayDeque<>();
+ private final Map<Integer, Integer> fieldLevelDispatches = new HashMap<>();
private boolean isAggressivelyBatching() {
return aggressivelyBatching;
@@ -109,6 +113,31 @@
}
}
+ private void setFieldDispatchCount(int level, int fieldCount) {
+ fieldLevelDispatches.put(level, fieldCount);
+ }
+
+ private int decrementFieldDispatchCount(int level) {
+ Integer currentCount = fieldLevelDispatches.getOrDefault(level, 1);
+ fieldLevelDispatches.put(level, currentCount - 1);
+ return currentCount;
+ }
+
+ private int getFieldDispatchCount(int level) {
+ return fieldLevelDispatches.getOrDefault(level, 0);
+ }
+
+ private boolean isOutstandingFieldFetchesFrom(int level) {
+ if (level < 0) {
+ return false;
+ }
+ int count = getFieldDispatchCount(level);
+ if (count > 0) {
+ return true;
+ }
+ return isOutstandingFieldFetchesFrom(--level);
+ }
+
@Override
public String toString() {
return "isInList=" + isInList();
@@ -123,6 +152,14 @@
private void dispatch() {
log.debug("Dispatching data loaders ({})", dataLoaderRegistry.getKeys());
+
+ System.out.println("\t\tDispatched!");
+ List<String> dlKeysWithData = dataLoaderRegistry.getKeys().stream().filter(key -> dataLoaderRegistry.getDataLoader(key).dispatchDepth() > 0).collect(Collectors.toList());
+ dlKeysWithData.forEach(key -> {
+ System.out.println(String.format("'%s' has %d depth", key, dataLoaderRegistry.getDataLoader(key).dispatchDepth()));
+ });
+
+ System.out.println("\n\n");
dataLoaderRegistry.dispatchAll();
}
@@ -140,7 +177,12 @@
}
private void dispatchIfNeeded(CallStack callStack, ExecutionStrategyParameters executionStrategyParameters) {
- if (isEndOfListOnAllLevels(executionStrategyParameters)) {
+ String where = "\t @" + executionStrategyParameters == null ? "" : executionStrategyParameters.path().toString();
+ System.out.println(where);
+
+ int level = executionStrategyParameters == null ? 0 : executionStrategyParameters.path().getLevel();
+ boolean outstandingDispatches = callStack.isOutstandingFieldFetchesFrom(level);
+ if (isEndOfListOnAllLevels(executionStrategyParameters) && ! outstandingDispatches) {
dispatch();
}
}
@@ -175,23 +217,34 @@
@Override
public InstrumentationContext<ExecutionResult> beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters) {
CallStack callStack = parameters.getInstrumentationState();
+ int level = parameters.getExecutionStrategyParameters().path().getLevel() + 1; // +1 because we are looking forward
+ int fieldCount = parameters.getExecutionStrategyParameters().fields().size();
+ callStack.setFieldDispatchCount(level, fieldCount);
return whenDispatched((result) -> dispatchIfNeeded(callStack, parameters.getExecutionStrategyParameters()));
}
+ @Override
+ public InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters) {
+ CallStack callStack = parameters.getInstrumentationState();
+ int level = parameters.getEnvironment().getFieldTypeInfo().getPath().getLevel();
+ callStack.decrementFieldDispatchCount(level);
+ return super.beginFieldFetch(parameters);
+ }
+
/*
- When graphql-java enters a field list it re-cursively called the execution strategy again, which will cause an early flush
- to the data loader - which is not efficient from a batch point of view. We want to allow the list of field values
- to bank up as promises and call dispatch when we are clear of a list value.
+ When graphql-java enters a field list it re-cursively called the execution strategy again, which will cause an early flush
+ to the data loader - which is not efficient from a batch point of view. We want to allow the list of field values
+ to bank up as promises and call dispatch when we are clear of a list value.
- https://github.com/graphql-java/graphql-java/issues/760
- */
+ https://github.com/graphql-java/graphql-java/issues/760
+ */
@Override
public InstrumentationContext<ExecutionResult> beginFieldListComplete(InstrumentationFieldCompleteParameters parameters) {
CallStack callStack = parameters.getInstrumentationState();
callStack.enterList();
return whenDispatched((result) -> {
callStack.exitList();
- dispatchIfNeeded(callStack, parameters.getExecutionStrategyParameters());
+ //dispatchIfNeeded(callStack, parameters.getExecutionStrategyParameters());
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment