feat(graphql): Reuse request results to improve performance #1452
+197
−31
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
If you have two observables for the same request, it will unnecessarily do extra (expensive) work
maybeRebroadcast
will diff, denormalize, and then require parsing againfetch(policy.cache)
will need to denormalize and require parsing againxyz
)Solution
I went with a solution that doesn't require changing any core flows or data structures. Slightly based on how Ferry keeps a map of requests.
The more observables you have for the same
Request
s, the bigger improvements you will see_getQueryResultByRequest
- Instead of introducing a new cache, we iterate through thequeries
array to find if any queries match theRequest
maybeRebroadcast
for afetch
from cache, we check this firstcopyWith
onQueryResult
lets us re-use the bulk of the existing query result (including the parsed data)Other improvement added - call maybeRebroadcast less
carryForwardDataOnException: false
in yourOptions
. I've found that behavior to match my expectations for failuresAddendum
maybeRebroadcast
uses a brute force approach to notifying of changes and relies on synchronicity (which definitely has its pros - like readability and reducing bugs). Which has led to jank/missed frames in our applicationmaybeRebroadcast
)maybeRebroadcast
is only unacceptable because it's on the main thread. It'd be fine on a separate thread.