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

Fix potential issue with nested @defer in non-deferrable case #2312

Merged
merged 2 commits into from
Jan 6, 2023

Conversation

pcmanus
Copy link
Contributor

@pcmanus pcmanus commented Jan 4, 2023

The code handling @defer works roughly like this:

  1. as we cross a query element (field or spread) with a @defer, we remember that we just "entered" a deferred section.
  2. as we handle the initial elements within that @defer, we notice that we just entered a @defer, ignore in which subgraph we were, and instead attempt to "re-enter" subgraphs using a key.
  3. if that work, we continue from whichever possible subgraphs we just re-entered.
  4. Otherwise, if we can't handle the new element by re-entering a subgraph, then we fall back to "normal" operation and try to handle the element from the original subgraph in which we were before entering the @defer: this correspond to case where we cannot do a router-based-defer due to not having proper @key to do it.

The issue however is that we were trying to re-enter subgraphs even when the next element was a fragment. This meant that we re-entered any subgraphs that had a key, but that may exclude the one subgraph in which we previously were. If we get a new @defer followed by a field that was only in the "original" subgraph, then we could end up not being able to find that field even when falling back to step 4 above, because we had already re-entered different subgraphs due to the 1st @defer.

The solution implemented by this commit consists in delaying the subgraph re-entry until we actually get to a field, since this is where we have to re-enter.

@netlify
Copy link

netlify bot commented Jan 4, 2023

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

Visit the deploys page to approve it

Name Link
🔨 Latest commit c791bf7

@pcmanus pcmanus self-assigned this Jan 4, 2023
@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 4, 2023

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.

Sylvain Lebresne added 2 commits January 6, 2023 16:35
The code handling `@defer` works roughly like this:
1. as we cross a query element (field or spread) with a `@defer`, we
  remember that we just "entered" a deferred section.
2. as we handle the initial elements within that `@defer`, we notice
  that we just entered a `@defer`, ignore in which subgraph we were,
  and instead attempt to "re-enter" subgraphs using a key.
3. if that work, we continue from whichever possible subgraphs we just
  re-entered.
4. Otherwise, if we can't handle the new element by re-entering a
  subgraph, then we fall back to "normal" operation and try to handle
  the element from the original subgraph in which we were before
  entering the @defer: this correspond to case where we cannot do a
  router-based-defer due to not having proper @key to do it.

The issue however is that we were trying to re-enter subgraphs even when
the next element was a fragment. This meant that we re-entered any
subgraphs that had a key, but that may exclude the one subgraph in which
we previously were. If we get a new `@defer` followed by a field that
was only in the "original" subgraph, then we could end up not being able
to find that field _even_ when falling back to step 4 above, because we
had already re-entered different subgraphs due to the 1st `@defer`.

The solution implemented by this commit consists in delaying the
subgraph re-entry until we actually get to a field, since this is where
we _have_ to re-enter.
@pcmanus pcmanus merged commit 5d96745 into apollographql:main Jan 6, 2023
pcmanus pushed a commit that referenced this pull request Jan 9, 2023
The code handling `@defer` works roughly like this:
1. as we cross a query element (field or spread) with a `@defer`, we
  remember that we just "entered" a deferred section.
2. as we handle the initial elements within that `@defer`, we notice
  that we just entered a `@defer`, ignore in which subgraph we were,
  and instead attempt to "re-enter" subgraphs using a key.
3. if that work, we continue from whichever possible subgraphs we just
  re-entered.
4. Otherwise, if we can't handle the new element by re-entering a
  subgraph, then we fall back to "normal" operation and try to handle
  the element from the original subgraph in which we were before
  entering the @defer: this correspond to case where we cannot do a
  router-based-defer due to not having proper @key to do it.

The issue however is that we were trying to re-enter subgraphs even when
the next element was a fragment. This meant that we re-entered any
subgraphs that had a key, but that may exclude the one subgraph in which
we previously were. If we get a new `@defer` followed by a field that
was only in the "original" subgraph, then we could end up not being able
to find that field _even_ when falling back to step 4 above, because we
had already re-entered different subgraphs due to the 1st `@defer`.

The solution implemented by this commit consists in delaying the
subgraph re-entry until we actually get to a field, since this is where
we _have_ to re-enter.
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.

2 participants