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 stripped nulls from response #3052

Closed
leoasis opened this issue Mar 22, 2020 · 5 comments
Closed

Handling stripped nulls from response #3052

leoasis opened this issue Mar 22, 2020 · 5 comments

Comments

@leoasis
Copy link
Contributor

leoasis commented Mar 22, 2020

At Twitter, our GraphQL API returns responses with null values stripped, in order to save bandwidth.

From our experience, this leads to quite some noticeable savings, and in some of our biggest responses (13-25k) we see a 5% reduction of the response after compression. Regarding uncompressed size, this goes down as much as ~25%.

While not technically spec compliant, this seems to be a nice performance optimization some servers could do, and the full response with null values should be able to be reconstructed client side, since Relay has the AST for the query that was used to make the request with.

Relay used to kind of support this at the normalizer level, but it was removed in this commit. Then it continued to work but causing a bunch of warnings of the type: RelayResponseNormalizer(): Payload did not contain a value for field <SOME_FIELD>. Check that you are parsing with the same query that was used to fetch the payload., and then in version 8.0.0 it stopped working completely with this commit, where a fragment with missing data would suspend.

I wonder if this is something that can be considered to be brought into Relay, if there's enough interest.

If this is not something that may be worth adding as a feature, at the very least it would be good to have some kind of way to know at the network layer the structure of the operation that was requested, as a way to reconstruct the missing fields from the response before Relay receives it.

@josephsavona
Copy link
Contributor

Thanks for posting and including detailed estimate of the size savings - those figures are definitely non-trivial so we can see how it could be beneficial to enable for your app. There wasn't a strong motivation for us to remove the feature - we primarily did so because it wasn't spec-compliant and we weren't using it. We'll discuss a bit internally and I'll follow-up here!

In the meantime - was anyone else using this feature? Were folks even aware that the option existed?

@sibelius
Copy link
Contributor

As a workaround for now you could disable the feature flag to avoid suspending your fragments

import RelayFeatureFlags from 'relay-runtime/lib/util/RelayFeatureFlags'
RelayFeatureFlags.ENABLE_RELAY_CONTAINERS_SUSPENSE = false

related to #3006

@josephsavona
Copy link
Contributor

We discussed internally and don't see any blockers to adding this back. The main points of discussion:

  • Q. What about optimistic updates? A. This feature should be disabled for optimistic updates and developers should have to provide keys for all fields (though they could still choose to provide an explicit undefined or null).
  • Q. Does this have any complications with suspense, especially @defer? A. Tl;dr No. If we did traverse into deferred fragments before we were sure the data was available this could be problematic when used in combination w suspense - we might think that a fragment was not pending because had populated null for its fields. But we intentionally avoid traversing into deferred fragments until we know the data (should) be available, so this isn't a problem.

So: we're open to PRs to re-enable this feature and can also add it to our internal backlog. If anyone is interested in working on this (@leoasis yourself included!) please let us know so that we don't also work on the same thing ourselves!

@leoasis
Copy link
Contributor Author

leoasis commented Mar 24, 2020

This is great to know! thanks for following up internally and reaching to a decision! I'll see if I can spend some time looking at this.

If I can find time to work on this, I'll let you know!

@leoasis
Copy link
Contributor Author

leoasis commented Apr 9, 2020

I think I can find some time to tackle this now! Will work on this in the next days

jstejada pushed a commit that referenced this issue Apr 29, 2020
Summary:
Adding the feature to handle stripped nulls in responses as an environment option, passing it through to the query executor and then to the response normalizer, which actually does the job of writing the fields with nulls or not based on the flag.

In the QueryExecutor, I explicitly passed the value to `false` when processing optimistic responses. I noticed that this path is not only used for optimistic responses defined in cases such as `commitMutation`, but also executed when the server may send an optimistic response using an extension. I think this case should still be stripping nulls, as those are coming from the server (if I understood correctly). Would love to confirm this and change the code so that I take into account that case (and change the test I added).

Also pass the value through for all the other async cases, such as defer, streams, module imports. I'm not very familiar with how those work and how they should play along with this option, so I'd appreciate some feedback. Based on [this comment](#3052 (comment)), it seems that based on how they are traversed it should not be an issue.

Finally, if this approach seems to be the way to go, happy to work on adding documentation for this (would love pointers on where would be the best place to put this).

Fixes #3052
Pull Request resolved: #3061

Reviewed By: josephsavona

Differential Revision: D21066513

Pulled By: jstejada

fbshipit-source-id: 86e34dc08cfcdacdc9b3679d847f3ddd1794240f
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 a pull request may close this issue.

3 participants