1111import graphql .execution .instrumentation .parameters .InstrumentationDeferredFieldParameters ;
1212import graphql .execution .instrumentation .parameters .InstrumentationExecutionStrategyParameters ;
1313import graphql .execution .instrumentation .parameters .InstrumentationFieldFetchParameters ;
14+ import graphql .language .Field ;
15+ import graphql .language .Selection ;
16+ import graphql .language .SelectionSet ;
17+ import graphql .schema .GraphQLOutputType ;
1418import org .dataloader .DataLoaderRegistry ;
1519import org .slf4j .Logger ;
1620import org .slf4j .LoggerFactory ;
1721
1822import java .util .Collections ;
1923import java .util .List ;
24+ import java .util .Optional ;
2025import java .util .concurrent .CompletableFuture ;
2126
2227/**
@@ -45,6 +50,8 @@ protected RequestStack getStack() {
4550 public ExecutionStrategyInstrumentationContext beginExecutionStrategy (InstrumentationExecutionStrategyParameters parameters ) {
4651 ExecutionId executionId = parameters .getExecutionContext ().getExecutionId ();
4752 ExecutionPath path = parameters .getExecutionStrategyParameters ().getPath ();
53+ List <Selection > selectionSet = Optional .ofNullable (parameters .getExecutionStrategyParameters ().getField ())
54+ .map (MergedField ::getSingleField ).map (Field ::getSelectionSet ).map (SelectionSet ::getSelections ).orElse (Collections .emptyList ());
4855 int parentLevel = path .getLevel ();
4956 int curLevel = parentLevel + 1 ;
5057 int fieldCount = parameters .getExecutionStrategyParameters ().getFields ().size ();
@@ -67,7 +74,7 @@ public void onCompleted(ExecutionResult result, Throwable t) {
6774 @ Override
6875 public void onFieldValuesInfo (List <FieldValueInfo > fieldValueInfoList ) {
6976 synchronized (stack ) {
70- stack .setStatus (executionId , handleOnFieldValuesInfo (fieldValueInfoList , stack , executionId , curLevel ));
77+ stack .setStatus (executionId , handleOnFieldValuesInfo (fieldValueInfoList , stack , executionId , curLevel , selectionSet ));
7178 if (stack .allReady ()) {
7279 dispatchWithoutLocking ();
7380 }
@@ -79,7 +86,7 @@ public void onDeferredField(MergedField field) {
7986 // fake fetch count for this field
8087 synchronized (stack ) {
8188 stack .increaseFetchCount (executionId , curLevel );
82- stack .setStatus (executionId , dispatchIfNeeded (stack , executionId , curLevel ));
89+ stack .setStatus (executionId , dispatchIfNeeded (stack , executionId , curLevel , selectionSet ));
8390 if (stack .allReady ()) {
8491 dispatchWithoutLocking ();
8592 }
@@ -91,7 +98,7 @@ public void onDeferredField(MergedField field) {
9198 //
9299 // thread safety : called with synchronised(stack)
93100 //
94- private boolean handleOnFieldValuesInfo (List <FieldValueInfo > fieldValueInfoList , RequestStack stack , ExecutionId executionId , int curLevel ) {
101+ private boolean handleOnFieldValuesInfo (List <FieldValueInfo > fieldValueInfoList , RequestStack stack , ExecutionId executionId , int curLevel , List < Selection > selectionSet ) {
95102 stack .increaseHappenedOnFieldValueCalls (executionId , curLevel );
96103 int expectedStrategyCalls = 0 ;
97104 for (FieldValueInfo fieldValueInfo : fieldValueInfoList ) {
@@ -102,7 +109,7 @@ private boolean handleOnFieldValuesInfo(List<FieldValueInfo> fieldValueInfoList,
102109 }
103110 }
104111 stack .increaseExpectedStrategyCalls (executionId , curLevel + 1 , expectedStrategyCalls );
105- return dispatchIfNeeded (stack , executionId , curLevel + 1 );
112+ return dispatchIfNeeded (stack , executionId , curLevel + 1 , selectionSet );
106113 }
107114
108115 private int getCountForList (FieldValueInfo fieldValueInfo ) {
@@ -121,6 +128,8 @@ private int getCountForList(FieldValueInfo fieldValueInfo) {
121128 public DeferredFieldInstrumentationContext beginDeferredField (InstrumentationDeferredFieldParameters parameters ) {
122129 ExecutionId executionId = parameters .getExecutionContext ().getExecutionId ();
123130 int level = parameters .getExecutionStrategyParameters ().getPath ().getLevel ();
131+ List <Selection > selectionSet = Optional .ofNullable (parameters .getExecutionStrategyParameters ().getField ())
132+ .map (MergedField ::getSingleField ).map (Field ::getSelectionSet ).map (SelectionSet ::getSelections ).orElse (Collections .emptyList ());
124133 synchronized (stack ) {
125134 stack .clearAndMarkCurrentLevelAsReady (executionId , level );
126135 }
@@ -138,7 +147,7 @@ public void onCompleted(ExecutionResult result, Throwable t) {
138147 @ Override
139148 public void onFieldValueInfo (FieldValueInfo fieldValueInfo ) {
140149 synchronized (stack ) {
141- stack .setStatus (executionId , handleOnFieldValuesInfo (Collections .singletonList (fieldValueInfo ), stack , executionId , level ));
150+ stack .setStatus (executionId , handleOnFieldValuesInfo (Collections .singletonList (fieldValueInfo ), stack , executionId , level , selectionSet ));
142151 if (stack .allReady ()) {
143152 dispatchWithoutLocking ();
144153 }
@@ -151,14 +160,16 @@ public void onFieldValueInfo(FieldValueInfo fieldValueInfo) {
151160 public InstrumentationContext <Object > beginFieldFetch (InstrumentationFieldFetchParameters parameters ) {
152161 ExecutionId executionId = parameters .getExecutionContext ().getExecutionId ();
153162 ExecutionPath path = parameters .getEnvironment ().getExecutionStepInfo ().getPath ();
163+ List <Selection > selectionSet = Optional .ofNullable (parameters .getEnvironment ().getField ())
164+ .map (Field ::getSelectionSet ).map (SelectionSet ::getSelections ).orElse (Collections .emptyList ());
154165 int level = path .getLevel ();
155166 return new InstrumentationContext <Object >() {
156167
157168 @ Override
158169 public void onDispatched (CompletableFuture result ) {
159170 synchronized (stack ) {
160171 stack .increaseFetchCount (executionId , level );
161- stack .setStatus (executionId , dispatchIfNeeded (stack , executionId , level ));
172+ stack .setStatus (executionId , dispatchIfNeeded (stack , executionId , level , selectionSet ));
162173
163174 if (stack .allReady ()) {
164175 dispatchWithoutLocking ();
@@ -176,16 +187,19 @@ public void onCompleted(Object result, Throwable t) {
176187 public void removeTracking (ExecutionId executionId ) {
177188 synchronized (stack ) {
178189 stack .removeExecution (executionId );
190+ if (stack .allReady ()) {
191+ dispatchWithoutLocking ();
192+ }
179193 }
180194 }
181195
182196
183197 //
184198 // thread safety : called with synchronised(stack)
185199 //
186- private boolean dispatchIfNeeded (RequestStack stack , ExecutionId executionId , int level ) {
200+ private boolean dispatchIfNeeded (RequestStack stack , ExecutionId executionId , int level , List < Selection > selectionSet ) {
187201 if (levelReady (stack , executionId , level )) {
188- return stack .dispatchIfNotDispatchedBefore (executionId , level );
202+ return stack .dispatchIfNotDispatchedBefore (executionId , level , selectionSet );
189203 }
190204 return false ;
191205 }
0 commit comments