@@ -66,6 +66,8 @@ private static class CallStack {
6666
6767 // this means one sub selection has been fully fetched
6868 // and the expected execute objects calls for the next level have been calculated
69+ // the level here is the level of the sub selection in order to avoid 0 levels, because
70+ // the root fields are on level 1
6971 private final LevelMap happenedOnFieldValueCallsPerLevel = new LevelMap ();
7072
7173 private final Set <Integer > dispatchedLevels = ConcurrentHashMap .newKeySet ();
@@ -85,9 +87,8 @@ private static class CallStack {
8587
8688
8789 public CallStack () {
88- // in the first level there is only one sub selection,
89- // so we only expect one execute object call (which is actually an executionStrategy call)
90- expectedExecuteObjectCallsPerLevel .set (1 , 1 );
90+ // the first execute object happens on level 0 and there is only one: the start of the strategy
91+ expectedExecuteObjectCallsPerLevel .set (0 , 1 );
9192 }
9293
9394 public void addResultPathWithDataLoader (int level , ResultPathWithDataLoader resultPathWithDataLoader ) {
@@ -139,8 +140,8 @@ boolean allExecuteObjectCallsHappened(int level) {
139140 return happenedExecuteObjectCallsPerLevel .get (level ) == expectedExecuteObjectCallsPerLevel .get (level );
140141 }
141142
142- boolean allSubSelectionsFetchingHappened (int level ) {
143- return happenedOnFieldValueCallsPerLevel .get (level ) == expectedExecuteObjectCallsPerLevel .get (level );
143+ boolean allSubSelectionsFetchingHappened (int subSelectionLevel ) {
144+ return happenedOnFieldValueCallsPerLevel .get (subSelectionLevel ) == expectedExecuteObjectCallsPerLevel .get (subSelectionLevel - 1 );
144145 }
145146
146147 boolean allFetchesHappened (int level ) {
@@ -197,17 +198,19 @@ public void executeDeferredOnFieldValueInfo(FieldValueInfo fieldValueInfo, Execu
197198 @ Override
198199 public void executionStrategy (ExecutionContext executionContext , ExecutionStrategyParameters parameters ) {
199200 Assert .assertTrue (parameters .getExecutionStepInfo ().getPath ().isRootPath ());
200- increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (1 , parameters );
201+ // the execute object on level 0 is beginning of the strategy
202+ increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (0 , parameters );
201203 }
202204
203205 @ Override
204206 public void executionSerialStrategy (ExecutionContext executionContext , ExecutionStrategyParameters parameters ) {
205207 resetCallStack ();
206- increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (1 , 1 );
208+ increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (0 , 1 );
207209 }
208210
209211 @ Override
210212 public void executionStrategyOnFieldValuesInfo (List <FieldValueInfo > fieldValueInfoList ) {
213+ // the root fields are the root sub selection on level 1
211214 onFieldValuesInfoDispatchIfNeeded (fieldValueInfoList , 1 );
212215 }
213216
@@ -220,19 +223,21 @@ public void executionStrategyOnFieldValuesException(Throwable t) {
220223
221224 @ Override
222225 public void executeObject (ExecutionContext executionContext , ExecutionStrategyParameters parameters ) {
223- int curLevel = parameters .getExecutionStepInfo (). getPath ().getLevel () + 1 ;
226+ int curLevel = parameters .getPath ().getLevel ();
224227 increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (curLevel , parameters );
225228 }
226229
227230 @ Override
228231 public void executeObjectOnFieldValuesInfo (List <FieldValueInfo > fieldValueInfoList , ExecutionStrategyParameters parameters ) {
232+ // the level of the sub selection that is fully fetched is one level more than parameters level
229233 int curLevel = parameters .getPath ().getLevel () + 1 ;
230234 onFieldValuesInfoDispatchIfNeeded (fieldValueInfoList , curLevel );
231235 }
232236
233237
234238 @ Override
235239 public void executeObjectOnFieldValuesException (Throwable t , ExecutionStrategyParameters parameters ) {
240+ // the level of the sub selection that is errored is one level more than parameters level
236241 int curLevel = parameters .getPath ().getLevel () + 1 ;
237242 callStack .lock .runLocked (() ->
238243 callStack .increaseHappenedOnFieldValueCalls (curLevel )
@@ -246,7 +251,8 @@ private void increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount(int curL
246251 private void increaseHappenedExecuteObjectAndIncreaseExpectedFetchCount (int curLevel , int fieldCount ) {
247252 callStack .lock .runLocked (() -> {
248253 callStack .increaseHappenedExecuteObjectCalls (curLevel );
249- callStack .increaseExpectedFetchCount (curLevel , fieldCount );
254+ // the fetch happens on the next level
255+ callStack .increaseExpectedFetchCount (curLevel + 1 , fieldCount );
250256 });
251257 }
252258
@@ -258,7 +264,7 @@ private void resetCallStack() {
258264 callStack .clearFetchCount ();
259265 callStack .clearHappenedExecuteObjectCalls ();
260266 callStack .clearHappenedOnFieldValueCalls ();
261- callStack .expectedExecuteObjectCallsPerLevel .set (1 , 1 );
267+ callStack .expectedExecuteObjectCallsPerLevel .set (0 , 1 );
262268 callStack .dispatchingFinishedPerLevel .clear ();
263269 callStack .dispatchingStartedPerLevel .clear ();
264270 callStack .allResultPathWithDataLoader .clear ();
@@ -282,11 +288,12 @@ private void onFieldValuesInfoDispatchIfNeeded(List<FieldValueInfo> fieldValueIn
282288 //
283289// thread safety: called with callStack.lock
284290//
291+ // this means a sub selection has been fully fetched
285292 private Integer handleOnFieldValuesInfo (List <FieldValueInfo > fieldValueInfos , int curLevel ) {
286293 callStack .increaseHappenedOnFieldValueCalls (curLevel );
287294 int expectedOnObjectCalls = getObjectCountForList (fieldValueInfos );
288- // on the next level we expect the following on object calls because we found non null objects
289- callStack .increaseExpectedExecuteObjectCalls (curLevel + 1 , expectedOnObjectCalls );
295+ // we expect on the level of the current sub selection #expectedOnObjectCalls execute object calls
296+ callStack .increaseExpectedExecuteObjectCalls (curLevel , expectedOnObjectCalls );
290297 // maybe the object calls happened already (because the DataFetcher return directly values synchronously)
291298 // therefore we check the next levels if they are ready
292299 // this means we could skip some level because the higher level is also already ready,
@@ -339,6 +346,7 @@ public void fieldFetched(ExecutionContext executionContext,
339346 private boolean dispatchIfNeeded (int level ) {
340347 boolean ready = checkLevelBeingReady (level );
341348 if (ready ) {
349+ System .out .println ("dispatchIfNeeded level " + level );
342350 callStack .setDispatchedLevel (level );
343351 return true ;
344352 }
@@ -379,21 +387,24 @@ private boolean checkLevelImpl(int level) {
379387 if (callStack .expectedFetchCountPerLevel .get (level ) == 0 ) {
380388 return false ;
381389 }
382- // level 1 is special: there is no previous sub selections
383- // and the expected execution object calls is always 1
384- if (level > 1 && !callStack .allSubSelectionsFetchingHappened (level - 1 )) {
390+
391+ // first we make sure that the expected fetch count is correct
392+ // by verifying that the parent level all execute object + sub selection were fetched
393+ if (!callStack .allExecuteObjectCallsHappened (level - 1 )) {
385394 return false ;
386395 }
387- if (!callStack .allExecuteObjectCallsHappened (level )) {
396+ if (level > 1 && !callStack .allSubSelectionsFetchingHappened (level - 1 )) {
388397 return false ;
389398 }
399+ // the main check: all fetches must have happened
390400 if (!callStack .allFetchesHappened (level )) {
391401 return false ;
392402 }
393403 return true ;
394404 }
395405
396406 void dispatch (int level ) {
407+ System .out .println ("dispatch level " + level );
397408 if (!enableDataLoaderChaining ) {
398409 DataLoaderRegistry dataLoaderRegistry = executionContext .getDataLoaderRegistry ();
399410 dataLoaderRegistry .dispatchAll ();
0 commit comments