Well this all depends on how you look at the GraphQL spec and how GraphQL gets translated into DQL. By specification each block of a query should executed separately, yes. But in my opinion this is highly based upon the implementation of the GraphQL server to do this. If someone was building a GraphQL server that did not support async easily such as my experience with PHP then having async functionality might not be possible in reality and the implementation might say oh well with this spec we will just do the best with what we have and that involves running each block synchronously. So knowing this leads to a door of possibility IF the rewriter can be smart enough to know what blocks to run as separate DQL queries and which blocks to run as one.
This would involve looking at what variables are exported by a block and what variables are used in a block and building a dependency tree of sorts. There might be a problem when a block exports two different variables that are used in two separate query blocks because with DQL it will throw errors if you have unused variables
But this idea is sort of using the references above showing how someone else obviously is breaking this spec rule in a purposeful way. Obviously they have to wait for the queries with export to finish before running the queries that use that export variable so that makes it more sync then async, yes.
So this begs the question, when is it okay for an implementation to break specification?
If the answer is never, then the references above pose a GraphQL server that is outside of spec.
If the answer is only on certain aspects of the spec under certain conditions when the results of the clients demand a break in the specification such as is the case with the referenced example server by the LogRocket Blog. And something I consider is what is the aspect of breaking the specification when an implementation chooses to break it on purpose? Breaking the spec of each block runs asynchronously implementing some* query blocks runs synchronously when needed creates no harmful effects on the clients besides possibly being a tad slower than what might be expected, but the tradeoff is having enhanced functionality.
I guess my bottom line is that this spec is already broken by languages implementing GraphQL that have to run everything synchronously already, so why would it matter if other languages that can run things asynchronously decide to on purpose break this rule on certain conditions.
I think the important aspect of the spec not to break in this situation is running mutations. Mutation blocks have to always run synchronously by specification.
GraphQL Specification regarding asynchronous/parallelization
ExecuteQuery(query, schema, variableValues, initialValue)
- Let queryType be the root Query type in schema.
- Assert: queryType is an Object type.
- Let selectionSet be the top level Selection Set in query.
- Let data be the result of running ExecuteSelectionSet(selectionSet, queryType, initialValue, variableValues) normally (allowing parallelization).
- Let errors be any field errors produced while executing the selection set.
- Return an unordered map containing data and errors.
6.2.1 Executing a Query
To execute a selection set, the object value being evaluated and the object type need to be known, as well as whether it must be executed serially, or may be executed in parallel.
6.3 Executing Selection Sets
Normally the executor can execute the entries in a grouped field set in whatever order it chooses (normally 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.
6.3.1 Normal and Serial Execution
It is common for resolver to be asynchronous due to relying on reading an underlying database or networked service to produce a value. This necessitates the rest of a GraphQL executor to handle an asynchronous execution flow.
6.4.2 Value Resolution note
- Return the result of evaluating ExecuteSelectionSet(subSelectionSet, objectType, result, variableValues) normally (allowing for parallelization).
6.4.3 Value Completion
According to the specification the language seems to be “allowing [for] parallelization”, “or executed in parallel”, “normally in parallel”, and to the point, “the server has the freedom to execute the field entries in whatever order it deems optimal”.
I don’t think implementing such a feature would break any kind of specification, because it does not seem to require for parallelization, but rather allow for it, which the implementation would still allow for it as long as the query blocks did not export vars that other query blocks were using.