-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fetch missing client edge server queries discovered in nested fragments #4992
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
This pull request was exported from Phabricator. Differential Revision: D74593372 |
Thanks for this @captbaritone , Ive patched our version of relay and this has fixed the majority of issues however its still failing when we are using For example: const { streamInfo } = readFragment(
graphql`
fragment audioUrlCloudcastFragment on Cloudcast
{
streamInfo {
url
}
}
`,
key,
); This is still missing the data, any idea what needs to update for this using your proposed approach? |
Thanks for trying it out and identifying this additional case. Could you clarify which filed is the client edge to server in this case? |
); | ||
// https://github.com/facebook/relay/issues/4882 | ||
it.each([[true], [false]])( | ||
'should fetch data missing in fragment spread within `@waterfall` field. CHECK_ALL_FRAGMENTS_FOR_MISSING_CLIENT_EDGES = %s', |
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.
@jonreading81 any chance you could create a repro unit test similar to this demonstrating the resolver issue you are seeing? If not, just providing more details might be able to help me construct one.
Nevermind, I think I have a repro of the issue you are seeing, and I think the note to myself above is likely the root cause. I'll update this pr. |
…olver root fragment (facebook#4994) Summary: As described by jonreading81 here: facebook#4992 (comment) Description of root cause: facebook#4992 (comment) Pull Request resolved: facebook#4994 Differential Revision: D74680616
Differential Revision: D74686987
…ts (facebook#4992) Summary: Pull Request resolved: facebook#4992 Initially reported here: facebook#4882 Fetching of client-edge-to-server generated queries is handled by detecting missing data in Relay Reader and Relay Reader maintaining a stack of client-edge-to-server fields. As we traverse into such fields we push information about that query onto the stack, and as we exit such fields we pop values off the stack. In the case of fragments spread into selections where we have such a stack built up, we propagate it via a hidden [__clientEdgeTraversalPath](https://github.com/facebook/relay/blob/35229211f1198b956382c604f7787ba3b99ab5ed/packages/relay-runtime/store/RelayStoreUtils.js#L281) field on fragment keys. This hidden property means that any fragment located somewhere underneath a client edge to server field might encounter missing data and need to trigger the fetch of that server query. For example, if the selection includes only fragment spreads, or some other query had fetched all the fields that were read directly in the fragment which read the actual resolver field the fragment with the resolver field would render fine and we wouldn't discover we were missing data until we tried to read a child fragment. In theory that could be many fragments away. E.g. if I had a field `my_client_edge_to_server` that returned a `User,` any fragment spread into any selection nested under that edge (including `my_client_edge_to_server.best_friend.favorite_sports_team.coach.profile_picture` could technically uncover missing data in some totally generic `ProfilePicture` fragment. However, we overlooked that possibility in D36684124 where we added an optimization which tries to avoid the overhead of these additional hooks in the common case by only checking for missing client edge data in the case that the fragment _itself_ contains at least one client edge field (as computed by the compiler). As the example above demonstrates (and the test case in this diff also demonstrates) that turns out to not actually be safe. This removes the optimization to allow the correct behavior to work. However, this adds a useMemo and useEffect to each useFragment, which may have some perf implications. Putting this behind a feature flag to let us ship this especially for folks who are blocked by it, but also so we can consider perf concerns before rolling out internally. I'll invert the feature flag default in a future diff once we've configured it internally. Differential Revision: D74593372
This pull request was exported from Phabricator. Differential Revision: D74593372 |
33f9ffd
to
49de64d
Compare
@jonreading81 I think this is the fix for the resolver issue you are seeing. Do you want to try patching that in as a well and see if it resolves the issue? I intend to land that as a separate PR since it is not strictly dependent on this one |
Thanks @captbaritone , I have tested this and it fixes the issue. Thanks for your quick response on this. |
…olver root fragment (#4994) Summary: As described by jonreading81 here: #4992 (comment) Description of root cause: #4992 (comment) Pull Request resolved: #4994 Reviewed By: tyao1 Differential Revision: D74680616 Pulled By: captbaritone fbshipit-source-id: ad320ef113bc1e220a5d62c02935f10940794076
This pull request has been merged in 611f6d9. |
@jonreading81 This should be available on NPM in the relay packages You'll need to set the feature flag. RelayFeatureFlags.CHECK_ALL_FRAGMENTS_FOR_MISSING_CLIENT_EDGES = true; |
Summary:
Initially reported here: #4882
Fetching of client-edge-to-server generated queries is handled by detecting missing data in Relay Reader and Relay Reader maintaining a stack of client-edge-to-server fields. As we traverse into such fields we push information about that query onto the stack, and as we exit such fields we pop values off the stack.
In the case of fragments spread into selections where we have such a stack built up, we propagate it via a hidden __clientEdgeTraversalPath field on fragment keys.
This hidden property means that any fragment located somewhere underneath a client edge to server field might encounter missing data and need to trigger the fetch of that server query.
For example, if the selection includes only fragment spreads, or some other query had fetched all the fields that were read directly in the fragment which read the actual resolver field the fragment with the resolver field would render fine and we wouldn't discover we were missing data until we tried to read a child fragment. In theory that could be many fragments away. E.g. if I had a field
my_client_edge_to_server
that returned aUser,
any fragment spread into any selection nested under that edge (includingmy_client_edge_to_server.best_friend.favorite_sports_team.coach.profile_picture
could technically uncover missing data in some totally genericProfilePicture
fragment.However, we overlooked that possibility in D36684124 where we added an optimization which tries to avoid the overhead of these additional hooks in the common case by only checking for missing client edge data in the case that the fragment itself contains at least one client edge field (as computed by the compiler).
As the example above demonstrates (and the test case in this diff also demonstrates) that turns out to not actually be safe.
This removes the optimization to allow the correct behavior to work. However, this adds a useMemo and useEffect to each useFragment, which may have some perf implications. Putting this behind a feature flag to let us ship this especially for folks who are blocked by it, but also so we can consider perf concerns before rolling out internally.
I'll invert the feature flag default in a future diff once we've configured it internally.
Differential Revision: D74593372