Skip to content

fix(gateway): merge selection sets of @requires fields #4064

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

Conversation

jakeblaxon
Copy link
Contributor

@jakeblaxon jakeblaxon commented May 4, 2020

This fixes a bug in the Apollo Gateway, where @requires fields are not provided to resolvers for fields nested more than one level deep.

What this is trying to fix

This aims to fix issue #3848: [Federation Gateway] @requires directive sometimes does not provide all required fields

Scenario

When requiring fields nested more than one level deep, they are not getting merged together into one selection set in the query plan. Instead, the query plan will contain duplicate sets like the following:

A {
    nested1 {
        nested2 {
            requiredValue
        }
    }
    nested1 {
        nested2 {
            userSpecifiedValue
        }
    }
}

The required value would be fetched but overwritten by the second selection set in the javascript object. This PR solves this issue by merging the selection sets together, to arbitrary depth, like the following:

A {
    nested1 {
        nested2 {
            requiredValue
            userSpecifiedValue
        }
    }
}

Fixes #3848
Closes #4017

@apollo-cla
Copy link

@jakeblaxon: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/

@jakeblaxon jakeblaxon changed the title [Gateway] Prevent @requires fields from being overwritten in the query plan fix(apollo-gateway): prevent @requires fields from being overwritten in the query plan May 4, 2020
@jakeblaxon jakeblaxon changed the title fix(apollo-gateway): prevent @requires fields from being overwritten in the query plan fix(apollo-gateway): prevent nested @requires fields from being overwritten in the query plan May 4, 2020
@jakeblaxon
Copy link
Contributor Author

Just noticed that #4017 appears to solve the same issue. I'll leave this PR open for now, but I'll go ahead and close it if #4017 gets merged in.

Copy link
Contributor

@trevor-scheer trevor-scheer left a comment

Choose a reason for hiding this comment

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

Thanks so much for taking the time to work on this @jakeblaxon! I've spoken with the author of the PR you linked, I'd like to go forward with your implementation if you're comfortable with the changes I'm suggesting.

If you're busy or unable to carry this forward for any reason please let me know and I'd be more than happy to wrap this up. Thanks again! 🎉

@trevor-scheer
Copy link
Contributor

Also, please add a changelog entry to the gateway changelog. Note: there's a separate changelog for gateway from the rest of the server monorepo.

@jakeblaxon
Copy link
Contributor Author

jakeblaxon commented May 17, 2020

Thanks, @trevor-scheer! I can get these changes in soon. One concern I want to bring up though is that this only combines selection sets for field nodes. If we were to get a fragment node that itself had nested subfields, that fragment node's selection set would still potentially override the corresponding field node's.

It currently appears that we expand any fragments into fields before calling selectionSetFromFieldSet(), so I haven't run into this issue, even when testing with fragments in the user query. I added the second test case, however, to catch this issue in case something changes in the future and we end up not expanding fragments before calling selectionSetFromFieldSet(). (You can see an example of this potential issue with the second test case that I added).

I noticed that in the #4017 implementation, since we pass context into selectionSetFromFieldSet(), we can potentially solve this issue, since we would then have access to that fragment node's corresponding selection set. (The reason I didn't address the fragment case was because I didn't have access to the selection set directly from the fragment node). If we continue to expand fragments before building the query plan, then this won't be necessary. If we don't continue this, however, we may want to consider going with #4017 so we can address the fragment case.

Curious to hear your thoughts. Thanks!

@trevor-scheer
Copy link
Contributor

@jakeblaxon the insight is very much appreciated. Let's go forward with this implementation. If we ever do go down that path, we can revisit Lenny's solution or adapt things as needed. Let me know if you need anything from me!

@jakeblaxon jakeblaxon requested a review from trevor-scheer May 19, 2020 03:24
Copy link
Contributor

@trevor-scheer trevor-scheer left a comment

Choose a reason for hiding this comment

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

Two minor changes within this review and this looks good to go! Thanks for the timely turnaround on these updates.

When I land this PR, do you mind if I attribute co-authorship to Lenny as well? I appreciate the effort that went into this from both of you!

FWIW, this is what that would look like in the final commit:
https://help.github.com/en/github/committing-changes-to-your-project/creating-a-commit-with-multiple-authors#creating-co-authored-commits-on-github

@jakeblaxon
Copy link
Contributor Author

@trevor-scheer Of course! Please add @lennyburdette as a co-author. Thank you!

@trevor-scheer trevor-scheer changed the title fix(apollo-gateway): prevent nested @requires fields from being overwritten in the query plan fix(gateway): merge selection sets of @requires fields May 21, 2020
@trevor-scheer trevor-scheer merged commit 3cdcd06 into apollographql:master May 21, 2020
@trevor-scheer
Copy link
Contributor

Thank you both for your time and efforts here, I'll have this released as a patch fix early next week!

@abernix
Copy link
Member

abernix commented May 28, 2020

Published in @apollo/[email protected]! 🎉 Thanks for this contribution!

abernix pushed a commit to apollographql/federation that referenced this pull request Sep 4, 2020
…ql/apollo-server#4064)

Previously, it was possible for the gateway to build and issue queries
for resolving fields that resembled the following:

```graphql
{
  product { id }
  product { price }
}
```

In the above example, the second selection set will take precedence and
the first ignored, meaning the query _ought_ to be:

```graphql
{
  product { id price }
}
```

This is accomplished in this PR by merging the selection sets recursively.

fixes apollographql/apollo-server#3848

Co-authored-by: Lenny Burdette <[email protected]>
Apollo-Orig-Commit-AS: apollographql/apollo-server@3cdcd06
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Federation Gateway] @requires directive sometimes does not provide all required fields
6 participants