Search code examples
graphqlgraphql-java

Is GraphQL cancelling data fetching in case of a failure?


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?


Solution

  • 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.