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

Stop delivering "stale" results to ObservableQuery. #6058

Merged
merged 9 commits into from
Apr 6, 2020

Conversation

benjamn
Copy link
Member

@benjamn benjamn commented Mar 18, 2020

One of the most counterintuitive and confusing behaviors of Apollo Client is to silently re-deliver previous results whenever an incomplete result is read from the cache here:

      // If there is some data missing and the user has told us that they
      // do not tolerate partial data then we want to return the previous
      // result and mark it as stale.
      const stale = !diff.complete && !(
        returnPartialData ||
        partialRefetch ||
        fetchPolicy === 'cache-only'
      );

      const lastResult = observableQuery.getLastResult();
      const resultFromStore: ApolloQueryResult<T> = {
        data: stale ? lastResult && lastResult.data : diff.result,
        loading: isNetworkRequestInFlight(networkStatus),
        networkStatus,
        stale,
      };

      // If the query wants updates on errors, add them to the result.
      if (errorPolicy === 'all' && hasGraphQLErrors) {
        resultFromStore.errors = graphQLErrors;
      }

      observer.next(resultFromStore);

Consider how pointless this is: we obtain observableQuery.getLastResult() and then send it immediately back to the ObservableQuery, just because it doesn't seem safe to send the incomplete diff.result.

Instead, we should never be sending stale or incomplete results to the ObservableQuery. And instead of silently dropping the stale results, we should report appropriate errors to the ObservableQuery via observer.error, so that the application can handle them. That's what this PR does.

I have not finished validating these changes against @ahrnee's reproduction in #5991 (hence the WIP status of the PR), but that's my first priority tomorrow.

@codecov
Copy link

codecov bot commented Mar 18, 2020

Codecov Report

Merging #6058 into master will decrease coverage by 0.01%.
The diff coverage is 88.13%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6058      +/-   ##
==========================================
- Coverage   95.37%   95.36%   -0.02%     
==========================================
  Files          88       89       +1     
  Lines        3653     3666      +13     
  Branches      903      872      -31     
==========================================
+ Hits         3484     3496      +12     
  Misses        146      146              
- Partials       23       24       +1     
Impacted Files Coverage Δ
src/core/ObservableQuery.ts 97.70% <ø> (-0.03%) ⬇️
src/core/types.ts 100.00% <ø> (ø)
src/utilities/testing/observableToPromise.ts 91.17% <0.00%> (ø)
src/react/data/QueryData.ts 90.52% <79.31%> (-0.48%) ⬇️
src/cache/core/types/common.ts 100.00% <100.00%> (ø)
src/cache/index.ts 100.00% <100.00%> (ø)
src/cache/inmemory/readFromStore.ts 100.00% <100.00%> (ø)
src/core/QueryManager.ts 97.69% <100.00%> (+<0.01%) ⬆️
src/errors/ApolloError.ts 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0aacba4...70ae548. Read the comment docs.

if (errorPolicy === 'all' && hasGraphQLErrors) {
resultFromStore.errors = graphQLErrors;
} else if (isNonEmptyArray(diff.missing) &&
!equal(diff.result, {})) {
Copy link
Member Author

@benjamn benjamn Mar 18, 2020

Choose a reason for hiding this comment

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

My reasoning for this !equal(diff.result, {}) check: results where zero fields were successfully read seem truly useless, and thus should not be reported to the client as errors, but partially successful reads with a few missing fields should be reported as errors.

@benjamn benjamn force-pushed the stop-delivering-stale-results branch 2 times, most recently from 88da9e5 to a3f9d18 Compare March 19, 2020 19:38
@benjamn benjamn force-pushed the stop-delivering-stale-results branch 2 times, most recently from 2762de3 to 14f2719 Compare April 3, 2020 19:35
@benjamn benjamn marked this pull request as ready for review April 3, 2020 23:16
@benjamn benjamn requested a review from hwillson April 3, 2020 23:16
Copy link
Member

@hwillson hwillson left a comment

Choose a reason for hiding this comment

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

This all looks excellent @benjamn - and the new missing field logging is going to be super helpful! 🎉

benjamn added 8 commits April 6, 2020 13:17
This new MissingFieldError type provides more information about the
location where the error occurred within the result object, while also
hiding the InvariantError type as an implementation detail.

It's important to continue using the InvariantError type internally to
give rollup-plugin-invariant a chance to strip the error messages from
production builds.
@benjamn benjamn force-pushed the stop-delivering-stale-results branch from 14f2719 to 788517f Compare April 6, 2020 17:17
@benjamn benjamn merged commit 963b7c2 into master Apr 6, 2020
@benjamn benjamn deleted the stop-delivering-stale-results branch April 6, 2020 17:23
benjamn added a commit that referenced this pull request May 7, 2020
This functionality was introduced in PR #6058 (beta.43), and was
temporarily removed by my refactoring PR #6221.

I believe these warnings can be improved, especially since they are pretty
noisy right now, but I wanted to preserve existing functionality before
trying to figure out a better way to report missing fields.

Any/all ideas and feedback welcome.
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants