Class ExecutionStrategy

java.lang.Object
graphql.execution.ExecutionStrategy
Direct Known Subclasses:
AbstractAsyncExecutionStrategy, SubscriptionExecutionStrategy

@PublicSpi public abstract class ExecutionStrategy extends Object
An execution strategy is give a list of fields from the graphql query to execute and find values for using a recursive strategy.
     query {
          friends {
              id
              name
              friends {
                  id
                  name
              }
          }
          enemies {
              id
              name
              allies {
                  id
                  name
              }
          }
     }

 

Given the graphql query above, an execution strategy will be called for the top level fields 'friends' and 'enemies' and it will be asked to find an object to describe them. Because they are both complex object types, it needs to descend down that query and start fetching and completing fields such as 'id','name' and other complex fields such as 'friends' and 'allies', by recursively calling to itself to execute these lower field layers

The execution of a field has two phases, first a raw object must be fetched for a field via a DataFetcher which is defined on the GraphQLFieldDefinition. This object must then be 'completed' into a suitable value, either as a scalar/enum type via coercion or if it's a complex object type by recursively calling the execution strategy for the lower level fields.

The first phase (data fetching) is handled by the method fetchField(ExecutionContext, ExecutionStrategyParameters)

The second phase (value completion) is handled by the methods completeField(ExecutionContext, ExecutionStrategyParameters, Object) and the other "completeXXX" methods.

The order of fields fetching and completion is up to the execution strategy. As the graphql specification http://spec.graphql.org/October2021/#sec-Normal-and-Serial-Execution says:

Normally the executor can execute the entries in a grouped field set in whatever order it chooses (often in parallel). Because the resolution of fields other than top-level mutation fields must always be side effect-free and idempotent, the execution order must not affect the result, and hence the server has the freedom to execute the field entries in whatever order it deems optimal.

So in the case above you could execute the fields depth first ('friends' and its sub fields then do 'enemies' and its sub fields or it could do breadth first ('fiends' and 'enemies' data fetch first and then all the sub fields) or in parallel via asynchronous facilities like CompletableFutures.

execute(ExecutionContext, ExecutionStrategyParameters) is the entry point of the execution strategy.