I am trying to understand if (Java) implementation of GraphQL is smart enough to cancel scheduled fetching of data if an exception is thrown during execution of one of the fetchers?
An example would be that I run a single query to retrieve all orders for a customer. Let's say that the customer has 100 orders. That means GraphQL should make 100 calls to retrieve details for each order, but halfway during the execution one of the calls fail - 49 requests have already succeeded, 50th failed, 50 more requests to go. GraphQL will break the ongoing execution of the query and will immediately return an error to the client. But will it make the remaining 50 calls or not?
That means GraphQL should make 100 calls to retrieve details for each order
It must call the resolver function 100 times, but whether that means 100 network calls or not is up to you. Nothing preventing you to batch-load all 100 in 1 network request (if the API permits it).
GraphQL will break the ongoing execution of the query and will immediately return an error to the client.
This only happens if you throw AbortExecutionException, otherwise the next node will get processed as normal. Partial results are the norm in GraphQL. One erroneous list element does not prevent all the others from resolving. As Ken Chan noted, this behavior is described by the spec.
How the query gets executed is very much in your hands. If it's all synchronous, and you interrupt the execution with an AbortExecutionException, then no further call will be made. If you dispatch async requests (by returning a CompletionStage e.g. CompletableFuture), there's no general mechanism in Java to interrupt those tasks. When you cancel a CompletableFuture, it does not interrupt the underlying thread. Even more insanely, it can not even propagate the cancellation to the previous CompletionStages. This is a Java problem, not GraphQL or graphql-java specific at all. You have to come up with non trivial machinery to enable this. One way would perhaps be to use Tascalate Concurrent, as it allows cancellation propagation and thread interruption. You still need to implement your tasks in a way to actually react to interruptions. So the bulk of the work is on you.
No , it will keep making the remaining 50 calls because it is required by the specification here ,point 3c :
Return a list where each list item is the result of calling CompleteValue(innerType, fields, resultItem, variableValues), where resultItem is each item in result.
But it will report to you that the order 50 is failed and its failure reason. At the end, you will get the JSON response similar to :
{
"data" : {
"orders" : [
{"id" : 1 , ..... } ,
{"id" : 2 , ..... } ,
{"id" : 3 , ..... } ,
......
]
},
"errors" : [
{
"message" : "Fail to get this order details due to blablab..." ,
"path" : [ "orders", 50 ]
}
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With