3
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?
3 Answers
Reset to default
3
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 CompletionStage
s. 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.
1
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 ]
}
]
}
1
-
Probably I didn't phrase my question correctly. Why does GQL have to make those remaining 50 calls if they will not have any impact on the overall response? These calls will by just a waste of resources. I can't see the conflict with the specification. Just to make sure I'm clear: the query is "get all orders for customerId=123". It is not "get details for all orderIds=[1,2,3,4,…]".
– Rado BuranskyJun 25, 2019 at 17:16
0
@kaqqao Is there a solution for same problem statement but in ApolloServer (using typescript) ?
1
-
This does not provide an answer to the question. You can search for similar questions, or refer to the related and linked questions on the right-hand side of the page to find an answer. If you have a related but different question, ask a new question, and include a link to this one to help provide context. See: Ask questions, get answers, no distractions
– Natty16 mins ago
Not the answer you're looking for? Browse other questions tagged
or ask your own question.
or ask your own question.
|