@@ -56,6 +56,55 @@ class EngineRunningTest extends Specification {
5656 states == [RUNNING , NOT_RUNNING ]
5757 }
5858
59+ def " multiple async DF" () {
60+ given :
61+ def sdl = '''
62+
63+ type Query {
64+ hello: String
65+ hello2: String
66+ }
67+ '''
68+ CompletableFuture cf1 = new CompletableFuture ();
69+ def df1 = { env ->
70+ return cf1;
71+ } as DataFetcher
72+ CompletableFuture cf2 = new CompletableFuture ();
73+ def df2 = { env ->
74+ return cf2;
75+ } as DataFetcher
76+
77+ def fetchers = [" Query" : [" hello" : df1, " hello2" : df2]]
78+ def schema = TestUtil . schema(sdl, fetchers)
79+ def graphQL = GraphQL . newGraphQL(schema). build()
80+
81+ def query = " { hello hello2 }"
82+ def ei = newExecutionInput(query). build()
83+
84+ List<RunningState > states = trackStates(ei)
85+
86+ when :
87+ def er = graphQL. executeAsync(ei)
88+ then :
89+ states == [RUNNING , NOT_RUNNING ]
90+
91+ when :
92+ states. clear();
93+ cf1. complete(" world" )
94+
95+ then :
96+ states == [RUNNING , NOT_RUNNING ]
97+
98+ when :
99+ states. clear()
100+ cf2. complete(" world2" )
101+
102+ then :
103+ states == [RUNNING , NOT_RUNNING ]
104+ er. get(). data == [hello : " world" , hello2 : " world2" ]
105+ }
106+
107+
59108 def " engine running state is observed with one async datafetcher" () {
60109 given :
61110 def sdl = '''
@@ -172,6 +221,64 @@ class EngineRunningTest extends Specification {
172221 states == [RUNNING , NOT_RUNNING ]
173222 }
174223
224+ def " async datafetcher failing with async exception handler" () {
225+ given :
226+ def sdl = '''
227+
228+ type Query {
229+ hello: String
230+ }
231+ '''
232+ def cf = new CompletableFuture ();
233+ def df = { env ->
234+ return cf. thenApply { it -> throw new RuntimeException (" boom" ) }
235+ } as DataFetcher
236+
237+ ReentrantLock reentrantLock = new ReentrantLock ()
238+ reentrantLock. lock();
239+
240+ def exceptionHandler = { param ->
241+ def async = CompletableFuture . supplyAsync {
242+ reentrantLock. lock();
243+ return DataFetcherExceptionHandlerResult . newResult(GraphqlErrorBuilder
244+ .newError(param. dataFetchingEnvironment). message(" recovered" ). build()). build()
245+ }
246+ return async
247+ } as DataFetcherExceptionHandler
248+
249+ def fetchers = [" Query" : [" hello" : df]]
250+ def schema = TestUtil . schema(sdl, fetchers)
251+ def graphQL = GraphQL . newGraphQL(schema). defaultDataFetcherExceptionHandler(exceptionHandler). build()
252+
253+ def query = " { hello }"
254+ def ei = newExecutionInput(query). build()
255+
256+ List<RunningState > states = trackStates(ei)
257+
258+ when :
259+ def er = graphQL. executeAsync(ei)
260+
261+ then :
262+ states == [RUNNING , NOT_RUNNING ]
263+
264+ when :
265+ states. clear()
266+ cf. complete(" foo" )
267+
268+ then :
269+ states == [RUNNING , NOT_RUNNING ]
270+
271+ when :
272+ states. clear()
273+ reentrantLock. unlock()
274+ def result = er. get()
275+
276+ then :
277+ result. errors. collect { it. message } == [" recovered" ]
278+ // we expect simply going from running to finshed
279+ states == [RUNNING , NOT_RUNNING ]
280+ }
281+
175282
176283 def " engine running state is observed with two async datafetcher" () {
177284 given :
0 commit comments