11package graphql .schema ;
22
33import graphql .Internal ;
4+ import graphql .execution .Async ;
45import graphql .execution .incremental .AlternativeCallContext ;
56import graphql .execution .instrumentation .dataloader .ExhaustedDataLoaderDispatchStrategy ;
67import graphql .execution .instrumentation .dataloader .PerLevelDataLoaderDispatchStrategy ;
1011import org .jspecify .annotations .NullMarked ;
1112import org .jspecify .annotations .Nullable ;
1213
14+ import java .util .ArrayList ;
15+ import java .util .HashMap ;
16+ import java .util .List ;
17+ import java .util .Map ;
1318import java .util .concurrent .CompletableFuture ;
1419
20+ import static graphql .Assert .assertNotNull ;
21+
1522@ Internal
1623@ NullMarked
1724public class DataLoaderWithContext <K , V > extends DelegatingDataLoader <K , V > {
@@ -29,9 +36,54 @@ public CompletableFuture<V> load(@NonNull K key, @Nullable Object keyContext) {
2936 // calling super.load() is important, because otherwise the data loader will sometimes called
3037 // later than the dispatch, which results in a hanging DL
3138 CompletableFuture <V > result = super .load (key , keyContext );
39+ newDataLoaderInvocation ();
40+ return result ;
41+ }
42+
43+
44+ @ Override
45+ public CompletableFuture <List <V >> loadMany (List <K > keys , List <Object > keyContexts ) {
46+ assertNotNull (keys );
47+ assertNotNull (keyContexts );
48+
49+ CompletableFuture <List <V >> result ;
50+ synchronized (this ) {
51+ List <CompletableFuture <V >> collect = new ArrayList <>(keys .size ());
52+ for (int i = 0 ; i < keys .size (); i ++) {
53+ K key = keys .get (i );
54+ Object keyContext = null ;
55+ if (i < keyContexts .size ()) {
56+ keyContext = keyContexts .get (i );
57+ }
58+ collect .add (delegate .load (key , keyContext ));
59+ }
60+ result = Async .allOf (collect );
61+ }
62+ newDataLoaderInvocation ();
63+ return result ;
64+ }
65+
66+ @ Override
67+ public CompletableFuture <Map <K , V >> loadMany (Map <K , ?> keysAndContexts ) {
68+ assertNotNull (keysAndContexts );
69+
70+ CompletableFuture <Map <K , V >> result ;
71+ synchronized (this ) {
72+ Map <K , CompletableFuture <V >> collect = new HashMap <>(keysAndContexts .size ());
73+ for (Map .Entry <K , ?> entry : keysAndContexts .entrySet ()) {
74+ K key = entry .getKey ();
75+ Object keyContext = entry .getValue ();
76+ collect .put (key , delegate .load (key , keyContext ));
77+ }
78+ result = Async .allOf (collect );
79+ }
80+ newDataLoaderInvocation ();
81+ return result ;
82+ }
83+
84+ private void newDataLoaderInvocation () {
3285 DataFetchingEnvironmentImpl dfeImpl = (DataFetchingEnvironmentImpl ) dfe ;
3386 DataFetchingEnvironmentImpl .DFEInternalState dfeInternalState = (DataFetchingEnvironmentImpl .DFEInternalState ) dfeImpl .toInternal ();
34- dfeInternalState .getProfiler ().dataLoaderUsed (dataLoaderName );
3587 if (dfeInternalState .getDataLoaderDispatchStrategy () instanceof PerLevelDataLoaderDispatchStrategy ) {
3688 AlternativeCallContext alternativeCallContext = dfeInternalState .getDeferredCallContext ();
3789 int level = dfeImpl .getLevel ();
@@ -40,6 +92,9 @@ public CompletableFuture<V> load(@NonNull K key, @Nullable Object keyContext) {
4092 AlternativeCallContext alternativeCallContext = dfeInternalState .getDeferredCallContext ();
4193 ((ExhaustedDataLoaderDispatchStrategy ) dfeInternalState .dataLoaderDispatchStrategy ).newDataLoaderInvocation (alternativeCallContext );
4294 }
43- return result ;
4495 }
96+
97+
98+
99+
45100}
0 commit comments