Skip to content
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

Handling of @defer in the query planner #1958

Merged
merged 15 commits into from
Aug 5, 2022

Conversation

pcmanus
Copy link
Contributor

@pcmanus pcmanus commented Jul 5, 2022

Experimental support for @defer in the query planner

@netlify
Copy link

netlify bot commented Jul 5, 2022

👷 Deploy request for apollo-federation-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 323c16e

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jul 5, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@pcmanus pcmanus marked this pull request as ready for review July 18, 2022 09:13
An oversight from a previous change ensured that when adding a field
selection to another selection set, we made sure the "rebase" the added
selection on the proper schema, but forgot to handle fragment elements.
This created issues in some cases when building `@defer` subselection in
the query plans, though isn't defer-specific so may have created issue
in other non-defer cases (?).

In any case, this commit fix that issue, but that actually encovered
another issue which is that when we extract subgraph from the
supergraph, we forget to add executable directives from the supergraph.
Meaning that the extract subgraph may not have the definition for
custom executable directive that _are_ copied to subgraph fetches.
But someone, the previous was hidding this problem _for the unit test
that tests execute directives_ (again, this probably created other
issues but ...).
Sylvain Lebresne and others added 5 commits July 22, 2022 10:15
…hQL-js

The `@defer` directive has been added as a built-in in the internal `Schema`
abstraction, but that means it doesn't get included when converting to a
graphQL-js `GraphQLSchema` object. And at least until we link against a
version of graphQL-js with `@defer` support, we should have a way to
ship the definition. This commit adds an option to
`Schema.toGraphQLJSSchema` to do just that.

Note that this is an option because whether the definition of `@defer`
is desirable depends on what the caller do: if the resulting schema is
meant to be used by a server that does not handle `@defer` (either
because it does not support it, or because it's explicitely disabled
by configuration), then it does not make sense to add the `@defer`
definition, this would be misleading.
Notice a slightly inefficiencies with direct nesting for entity types
and added a TODO. Will fix that later, but it's only an inefficiency and
the generated plan will technically return the proper result.
Copy link
Contributor

@benweatherman benweatherman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐐

@benweatherman benweatherman enabled auto-merge (squash) August 5, 2022 18:11
@benweatherman benweatherman merged commit 816a9ad into apollographql:main Aug 5, 2022
Copy link
Member

@glasser glasser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a high level review of this (not going into the depths of the query planner, which I'm not familiar with) to see if I could bring anything helpful to the table and to help me understand the overall query plan structure for this defer implementation. Hope this helps!

@@ -1072,8 +1099,50 @@ const graphQLBuiltInDirectivesSpecifications: readonly DirectiveSpecification[]
locations: [DirectiveLocation.SCALAR],
argumentFct: (schema) => ({ args: [{ name: 'url', type: new NonNullType(schema.stringType()) }], errors: [] })
}),
// TODO: currently inconditionally adding @defer as the list of built-in. It's probably fine, but double check if we want to not do so when @defer-support is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general concept is that if @defer is "part of the schema" (visible via introspection if introspection is on, passes validation when included in an operation) then the server should "support defer" (though it could choose to not defer particular deferred fragments anyway).

internals-js/src/definitions.ts Show resolved Hide resolved
internals-js/src/definitions.ts Show resolved Hide resolved
query-planner-js/src/config.ts Show resolved Hide resolved
@glasser
Copy link
Member

glasser commented Aug 24, 2022

Oh one other note. There are subtleties in the current spec around mutations. Normal GraphQL serial execution says you completely finish everything rooted at one root mutation field before moving on to the next one. (I hope Router does this correctly already? I actually don't see any tests of mutations in buildPlan.test.ts from before this PR.) However, the decision for defer/stream is that deferred blocks should be an exception here: if some stuff under a mutation root field is deferred, the next mutation root field can start.

I think your mutation tests cover this correctly but I'm not entirely sure I'm mentally parsing the plans correctly to verify :)

pcmanus pushed a commit to pcmanus/federation that referenced this pull request Aug 29, 2022
This address most of the comment from @glasser on apollographql#1958, namely:
- it removes/update some outdated TODOs.
- it fixup the definition of @defer/@stream to match current spec.
- makes serialized query plan for condition hopefully a tad easier to
  parse (solely impact unit tests readability).
- adds a test to ensure that if the same field is queries both "normally"
  and deferred, we do query it twice (that's what spec specifies).
pcmanus pushed a commit that referenced this pull request Aug 29, 2022
…2093)

An optimisation recently made to the handling of fragments was mistakenly forgetting to look for directive applications on fragments and as a result those application were lost when that optimisation kicked in. In particular, this could make some `@defer` on a named fragments be completely ignored. This patch fixes this by simply avoiding the optimisation in question when there is applied directives, thus preserving them.

Additionally, this commit addresses comments from @glasser on #1958, namely:
- it removes/update some outdated TODOs.
- it fixes up the definition of @defer/@stream to match current spec.
- makes serialized query plan for condition hopefully a tad easier to parse (solely impact unit tests readability).
- adds a test to ensure that if the same field is queries both "normally" and deferred, we do query it twice (that's what spec specifies).
@pcmanus pcmanus linked an issue Aug 31, 2022 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deliver: @defer support in the query planner
3 participants