@@ -19,13 +19,16 @@ import org.dataloader.DataLoaderRegistry
1919import org.reactivestreams.Publisher
2020import reactor.core.publisher.Mono
2121import spock.lang.Specification
22+ import spock.lang.Unroll
2223
2324import java.time.Duration
2425import java.util.concurrent.CompletableFuture
2526import java.util.concurrent.CompletionStage
2627
2728import static graphql.ExecutionInput.newExecutionInput
2829import static graphql.StarWarsSchema.starWarsSchema
30+ import static graphql.execution.instrumentation.dataloader.DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_CHAINING
31+ import static graphql.execution.instrumentation.dataloader.DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING
2932import static graphql.schema.idl.RuntimeWiring.newRuntimeWiring
3033import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring
3134
@@ -56,6 +59,7 @@ class DataLoaderDispatcherTest extends Specification {
5659 ]
5760
5861
62+ @Unroll
5963 def " basic dataloader dispatch test" () {
6064 def dispatchedCalled = false
6165 def dataLoaderRegistry = new DataLoaderRegistry ()
@@ -69,14 +73,17 @@ class DataLoaderDispatcherTest extends Specification {
6973
7074 def graphQL = GraphQL . newGraphQL(starWarsSchema). build()
7175 def executionInput = newExecutionInput(). dataLoaderRegistry(dataLoaderRegistry). query(' { hero { name } }' ). build()
72- executionInput. getGraphQLContext(). put( DataLoaderDispatchingContextKeys . ENABLE_DATA_LOADER_CHAINING , false )
76+ executionInput. getGraphQLContext(). putAll(contextKey == null ? Collections . emptyMap() : [(contextKey): true ] )
7377
7478 when :
7579 def er = graphQL. executeAsync(executionInput)
7680 Awaitility . await(). until { er. isDone() }
7781 then :
7882 er. get(). data == [hero : [name : ' R2-D2' ]]
7983
84+ where :
85+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
86+
8087 }
8188
8289 def " enhanced execution input is respected" () {
@@ -112,6 +119,7 @@ class DataLoaderDispatcherTest extends Specification {
112119 }
113120
114121
122+ @Unroll
115123 def " ensure DataLoaderDispatcher works for async serial execution strategy" () {
116124
117125 given :
@@ -126,16 +134,23 @@ class DataLoaderDispatcherTest extends Specification {
126134
127135 when :
128136
129- def asyncResult = graphql. executeAsync(newExecutionInput(). query(query). dataLoaderRegistry(dlRegistry))
137+ def asyncResult = graphql. executeAsync(newExecutionInput(). query(query)
138+ .graphQLContext(contextKey == null ? Collections . emptyMap() : [(contextKey): true ])
139+ .dataLoaderRegistry(dlRegistry))
140+
130141
131142 Awaitility . await(). atMost(Duration . ofMillis(200 )). until { -> asyncResult. isDone() }
132143 def er = asyncResult. join()
133144
134145 then :
135146 er. data == expectedQueryData
136147
148+ where :
149+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
150+
137151 }
138152
153+ @Unroll
139154 def " basic batch loading is possible" () {
140155
141156 given :
@@ -146,7 +161,9 @@ class DataLoaderDispatcherTest extends Specification {
146161
147162 when :
148163
149- def asyncResult = graphql. executeAsync(newExecutionInput(). query(query). dataLoaderRegistry(dlRegistry))
164+ def asyncResult = graphql. executeAsync(newExecutionInput(). query(query)
165+ .graphQLContext(contextKey == null ? Collections . emptyMap() : [(contextKey): true ])
166+ .dataLoaderRegistry(dlRegistry))
150167
151168 def er = asyncResult. join()
152169
@@ -170,9 +187,14 @@ class DataLoaderDispatcherTest extends Specification {
170187 //
171188 // if we didn't have batch loading it would have these many character load calls
172189 starWarsWiring. naiveLoadCount == 15
190+
191+ where :
192+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
193+
173194 }
174195
175196
197+ @Unroll
176198 def " non list queries work as expected" () {
177199
178200 given :
@@ -201,7 +223,9 @@ class DataLoaderDispatcherTest extends Specification {
201223 }
202224 """
203225
204- def asyncResult = graphql. executeAsync(newExecutionInput(). query(query). dataLoaderRegistry(dlRegistry))
226+ def asyncResult = graphql. executeAsync(newExecutionInput(). query(query)
227+ .graphQLContext(contextKey == null ? Collections . emptyMap() : [(contextKey): true ])
228+ .dataLoaderRegistry(dlRegistry))
205229
206230 def er = asyncResult. join()
207231
@@ -213,8 +237,13 @@ class DataLoaderDispatcherTest extends Specification {
213237 starWarsWiring. rawCharacterLoadCount == 4
214238 starWarsWiring. batchFunctionLoadCount == 2
215239 starWarsWiring. naiveLoadCount == 8
240+
241+ where :
242+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
243+
216244 }
217245
246+ @Unroll
218247 def " can be efficient with lazily computed data loaders" () {
219248
220249 def sdl = '''
@@ -225,53 +254,62 @@ class DataLoaderDispatcherTest extends Specification {
225254
226255 BatchLoader batchLoader = { keys -> CompletableFuture . completedFuture(keys) }
227256
228- DataFetcher df = { env ->
229- def dataLoader = env. getDataLoaderRegistry(). computeIfAbsent(" key" , { key -> DataLoaderFactory . newDataLoader(batchLoader) })
230-
257+ def df = { env ->
258+ def dataLoader = env. getDataLoader(" key" )
231259 return dataLoader. load(" working as expected" )
232- }
260+ } as DataFetcher
233261 def runtimeWiring = newRuntimeWiring(). type(
234262 newTypeWiring(" Query" ). dataFetcher(" field" , df). build()
235263 ). build()
236264
237265 def graphql = TestUtil . graphQL(sdl, runtimeWiring). build()
238266
239267 DataLoaderRegistry dataLoaderRegistry = new DataLoaderRegistry ()
268+ def loader = DataLoaderFactory . newDataLoader(" key" , batchLoader)
269+ dataLoaderRegistry. register(" key" , loader)
240270
241271 when :
242272 def executionInput = newExecutionInput(). dataLoaderRegistry(dataLoaderRegistry). query(' { field }' ). build()
243- executionInput. getGraphQLContext(). put( DataLoaderDispatchingContextKeys . ENABLE_DATA_LOADER_CHAINING , false )
244- def er = graphql. execute (executionInput)
273+ executionInput. getGraphQLContext(). putAll(contextKey == null ? Collections . emptyMap() : [(contextKey): true ]);
274+ def erCF = graphql. executeAsync (executionInput)
245275
246276 then :
247- er. errors. isEmpty()
248- er. data[" field" ] == " working as expected"
277+ Awaitility . await(). until { erCF. isDone() }
278+ erCF. get(). errors. isEmpty()
279+ erCF. get(). data[" field" ] == " working as expected"
280+
281+ where :
282+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
249283 }
250284
285+ @Unroll
251286 def " handles deep async queries when a data loader registry is present" () {
252287 given :
253288 def support = new DeepDataFetchers ()
254289 def dummyDataloaderRegistry = new DataLoaderRegistry ()
255290 def graphql = GraphQL . newGraphQL(support. schema())
256291 .build()
257- // FieldLevelTrackingApproach uses LevelMaps with a default size of 16.
258- // Use a value greater than 16 to ensure that the underlying LevelMaps are resized
259- // as expected
260292 def depth = 50
261293
262294 when :
263295 def asyncResult = graphql. executeAsync(
264296 newExecutionInput()
265297 .query(support. buildQuery(depth))
298+ .graphQLContext(contextKey == null ? Collections . emptyMap() : [(contextKey): true ])
266299 .dataLoaderRegistry(dummyDataloaderRegistry)
267300 )
268301 def er = asyncResult. join()
269302
270303 then :
271304 er. errors. isEmpty()
272305 er. data == support. buildResponse(depth)
306+
307+ where :
308+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
309+
273310 }
274311
312+ @Unroll
275313 def " issue 3662 - dataloader dispatching can work with subscriptions" () {
276314
277315 def sdl = '''
@@ -298,7 +336,7 @@ class DataLoaderDispatcherTest extends Specification {
298336 }
299337
300338 DataFetcher dlDF = { DataFetchingEnvironment env ->
301- def dataLoader = env. getDataLoaderRegistry() . getDataLoader(" dl" )
339+ def dataLoader = env. getDataLoader(" dl" )
302340 return dataLoader. load(" working as expected" )
303341 }
304342 DataFetcher dlSub = { DataFetchingEnvironment env ->
@@ -332,6 +370,7 @@ class DataLoaderDispatcherTest extends Specification {
332370 def executionInput = newExecutionInput()
333371 .dataLoaderRegistry(dataLoaderRegistry)
334372 .query(query)
373+ .graphQLContext(contextKey == null ? Collections . emptyMap() : [(contextKey): true ])
335374 .build()
336375 def er = graphql. execute(executionInput)
337376
@@ -347,5 +386,8 @@ class DataLoaderDispatcherTest extends Specification {
347386
348387 def msgER = subscriber. getEvents()[0 ] as ExecutionResult
349388 msgER. data == [onSub : [x : " working as expected" , y : " working as expected" ]]
389+
390+ where :
391+ contextKey << [ENABLE_DATA_LOADER_CHAINING , ENABLE_DATA_LOADER_EXHAUSTED_DISPATCHING , null ]
350392 }
351393}
0 commit comments