-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Replace ExecuteSelectionSet
with ExecuteGroupedFieldSet
#1039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for graphql-spec-draft ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
4d62b8b
to
b342b58
Compare
(Rebased on |
b342b58
to
a52310e
Compare
(Rebased on |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
@benjie we need to formally define "grouped field set" in Section 2 "Language". You might have done so in a prior PR that I missed. Here is the link to us defining "section sets" in section 2 https://spec.graphql.org/draft/#sec-Selection-Sets |
This is up-to-date and ready-to-go again. @yaacovCR or @JoviDeCroock; please can you confirm this latest text still aligns with GraphQL.js. @Keweiqu Since a "grouped field set" is only part of execution and doesn't have an expression in the language I've not defined it in chapter 2, but in chapter 6 instead. (Here's where the current spec first introduces the term: https://spec.graphql.org/draft/#sel-FANRFABAB5EnhJ ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nits because we agreed to name things responseName
instead of responseKey
* Consistently use 'response key' not 'response name' * Extract definition of response key from #1039 * Utilise definition * response key -> response name * Fix names in algorithms * latest changes --------- Co-authored-by: Lee Byron <[email protected]>
@benjie this change looks good but has some conflicts with the other changes pulled out and recently merged. Want to rebase and fix? Then I'll get this one merged |
spec/Section 6 -- Execution.md
Outdated
:: A _grouped field set_ is a map where each entry is a list of field selections | ||
that share a _response name_ (the alias if defined, otherwise the field name). | ||
|
||
Before execution, the _selection set_ is converted to a _grouped field set_ by | ||
calling {CollectFields()}. This ensures all fields with the same response name | ||
(including those in referenced fragments) are executed at the same time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are the only lines that have actually been changed in Field Collection, everything else was just moved.
(To prove this, take the current Field Collection
text and paste it over this PR, the diff should render as:
diff --git i/spec/Section 6 -- Execution.md w/spec/Section 6 -- Execution.md
index f81e38d..549930f 100644
--- i/spec/Section 6 -- Execution.md
+++ w/spec/Section 6 -- Execution.md
@@ -374,12 +374,11 @@ serial):
### Field Collection
-:: A _grouped field set_ is a map where each entry is a list of field selections
-that share a _response name_ (the alias if defined, otherwise the field name).
-
-Before execution, the _selection set_ is converted to a _grouped field set_ by
-calling {CollectFields()}. This ensures all fields with the same response name
-(including those in referenced fragments) are executed at the same time.
+Before execution, the _selection set_ is converted to a grouped field set by
+calling {CollectFields()}. Each entry in the grouped field set is a list of
+fields that share a _response name_ (the alias if defined, otherwise the field
+name). This ensures all fields with the same response name (including those in
+referenced fragments) are executed at the same time.
As an example, collecting the fields of this selection set would collect two
instances of the field `a` and one of field `b`:
)
@leebyron I opted for a merge instead as it was less work, this is now good to review again. (I diffed the diffs and only the expected changes have come through, I also searched for "response key" and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really love this cleanup, much closer to GraphQL.js
@benjie I took a pass at some re-ordering of the content here, I'd be curious for your feedback. Also, I think "Grouped Field Set" has become a confusing name. Ideally this term "Collect" is what we use for this concept (instead of "group") and it's a bit weird this is called a "Set" when in fact its type is "Collected Field Map"? |
553dc1a
to
d68df95
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Scratch that. I'd be happy with "Collected Fields Map", but I think it's important "field" is plural, either via
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the edits @leebyron! I'm generally in favour, but have a few suggestions.
executed, then of those all subfields are collected, then each executed. This | ||
process continues until there are no more subfields to collect and execute. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be interpreted as a breadth-first execution (completing each layer before moving on to the next), but we actually execute depth first via value completion (assuming every field resolves synchronously).
Here's a small edit to avoid this misinterpretation
executed, then of those all subfields are collected, then each executed. This | |
process continues until there are no more subfields to collect and execute. | |
executed. As each field completes, all its subfields are collected, then each | |
executed. This process continues until there are no more subfields to collect | |
and execute. |
:: A _root selection set_ is the top level _selection set_ provided by a GraphQL | ||
operation. A root selection set always selects from a root type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Very happy to have this defined!
:: A _root selection set_ is the top level _selection set_ provided by a GraphQL | |
operation. A root selection set always selects from a root type. | |
:: A _root selection set_ is the top level _selection set_ provided by a GraphQL | |
operation. A root selection set always selects from a _root operation type_. |
|
||
- Let {groupedFieldSet} be the result of {CollectFields(objectType, | ||
selectionSet, variableValues)}. | ||
- Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet, | ||
objectType, initialValue, variableValues)} _serially_ if {executionMode} is | ||
{"serial"}, otherwise _normally_). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should restore the parenthesis, they add clarity to what "normally" means.
{"serial"}, otherwise _normally_). | |
{"serial"}, otherwise _normally_ (allowing parallelization)). |
:: A _grouped field set_ is a map where each entry is a _response name_ and a | ||
list of selected fields that share that _response name_ (the field alias if | ||
defined, otherwise the field's name). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we choose not to rename "grouped field set", we should at least define it in terms of a set:
:: A _grouped field set_ is a map where each entry is a _response name_ and a | |
list of selected fields that share that _response name_ (the field alias if | |
defined, otherwise the field's name). | |
:: A _grouped field set_ is a map where each entry is a _response name_ and an | |
ordered set of selected fields that share that _response name_ (the field alias | |
if defined, otherwise the field's name). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we accept this, we should also make a few other changes such as:
-Initialize groupedFields to an empty ordered map of lists.
+Initialize groupedFields to an empty ordered map of ordered sets.
When more than one field of the same name is executed in parallel, during value | ||
completion each related _selection set_ is collected together to produce a | ||
single _grouped field set_ in order to continue execution of the sub-selection | ||
sets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Text like this already exists in the spec as it stands today, but it is confusing. The "in parallel" sounds like it applies to serial versus parallel execution, but it doesn't since this still holds for mutation fields. Further the "same name" is also not quite right, because it's the response name that matters, not the actual field name - { cat: pet(id: 1) { name } dog: pet(id: 2) { age } }
would not merge selection sets.
The thing is, we don't execute a field (in the GraphQL request document AST sense1 - i.e. a "field selection") we actually execute a field set (i.e. a "set of field selections").
How about:
When more than one field of the same name is executed in parallel, during value | |
completion each related _selection set_ is collected together to produce a | |
single _grouped field set_ in order to continue execution of the sub-selection | |
sets. | |
When a field is executed, during value completion the _selection set_ of each of | |
the related field selections with the same response name are collected together | |
to produce a single _grouped field set_ in order to continue execution of the | |
sub-selection sets. |
Footnotes
-
We do execute a field in the GraphQL schema sense. Using "field" for both of these is quite confusing, I find. Maybe we should be more careful to use "field selection" rather than "field". ↩
Essentially this PR raises the concept of "grouped field sets" to be a top-level concept, and replaces the
ExecuteSelectionSet
method withExecuteGroupedFieldSet
(which essentially just drops the first line ofExecuteSelectionSet
, which was responsible for producing the grouped field set to be executed). It then refactors the rest of the spec to accommodate this change, reducing the repetition inExecuteQuery
,ExecuteMutation
andExecuteSubscriptionEvent
; and removingMergeSelectionSets
(which generated a "virtual" selection set to accomodate theExecuteSelectionSet
method), instead adding aCollectSubfields
algorithm which generates a grouped field set directly, ready for execution.I extracted this common refactoring from a number of my attempts to write spec changes for the
@defer
and@stream
directives - it turns out that this refactoring of the spec was always needed as a base for my changes. Similarly, @yaacovCR found similar in his attempts to address this same problem, and raised #999 extracted from his solution. This PR was introduced independently of #999 (other than using theCollectSubfields
algorithm name) however there is significant alignment, so @yaacovCR suggested that I raise it as an alternative PR.It may be easier to review this PR in "split" view rather than "unified" view.