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

AC3: ApolloCache.write* no longer updates cache silently (breaking change) #6262

Closed
jamshally opened this issue May 10, 2020 · 8 comments
Closed
Milestone

Comments

@jamshally
Copy link

jamshally commented May 10, 2020

Actual outcome:
Release AC3 v3.0.0-beta.40 and beyond:

  • ApolloCache.writeFragment triggers watched query broadcast: TRUE (breaking change)
  • ApolloClient.writeFragment triggers watched query broadcast: TRUE (as expected)

Release AC3 v3.0.0-beta.39 and before:

  • ApolloCache.writeFragment triggers watched query broadcast: FALSE (as expected)
  • ApolloClient.writeFragment triggers watched query broadcast: TRUE (as expected)

Intended outcome:

  • Known and consistent behavior of query broadcasts
  • A mechanism to update cache without triggering broadcasts (to improve performance in bulk update scenarios)
  • More generally - to understand the difference between calling ApolloClient.* and ApolloCache.* (and ideally have this in the documentation)

How to reproduce the issue:
The behavior change can be seen demonstrated in this react_apollo_error_template.

Repro steps:

  1. Click 'Update name via ApolloClient' button, and see that UI updates
  2. Click 'Update name via ApolloCache' button, and see that UI updates (breaking change)
  3. Update the @apollo/client dependency in package.json from 3.0.0-beta.46 to "3.0.0-beta.39"
  4. Click 'Update name via ApolloClient' button, and see that UI updates
  5. Click 'Update name via ApolloCache' button, and see that the UI does NOT update (as expected)

Related Questions
This issue, and review of the related source code, raised several questions I have been unable to find answers to in the documentation:

  1. Generally, what are the expected behavior differences between calling methods on the ApolloCache directly, and calling their counterparts via the ApolloClient (such as reads and writes), and what are the use cases for using one vs the other?

  2. The Cache has a (AFAIK undocumented) method: performTransaction. This seems useful for bulk-cache-update scenarios. Is this is intended for general use? And, why is it's counterpart not available on the ApolloClient?

  3. The ApolloClient and ApolloCache both seem to have their own independent queryWatch queues and broadcast mechanisms. This seems like it will have important (but hard to discern) behavior implications when using methods on ApolloCache directly vs via ApolloClient. Is there any documentation related to this, or can you describe the implications of this difference?

  4. (Bonus Question) When receiving the changed data via a watched query, the entire graph for the query is returned. Is there a mechanism to determine which pieces of the graph have changed? The ApolloClient seems to have some fairly fine-grained change-tracking internally, I just can't see an obvious way to access the details of what has changed.

Thanks

Versions
System:
OS: macOS 10.15.4
Binaries:
Node: 13.7.0 - /usr/local/bin/node
Yarn: 1.22.4 - ~/.yarn/bin/yarn
npm: 6.13.6 - /usr/local/bin/npm
Browsers:
Chrome: 81.0.4044.138
Safari: 13.1
npmPackages:
@apollo/client: 3.0.0-beta.46 => 3.0.0-beta.46

@jamshally jamshally changed the title AC3: ApolloCache.* Triggers Query Broadcasts (Behavior Breaking Change) AC3: ApolloCache.write* no longer updates cache silently May 10, 2020
@jamshally jamshally changed the title AC3: ApolloCache.write* no longer updates cache silently AC3: ApolloCache.write* no longer updates cache silently (breaking change) May 10, 2020
@benjamn
Copy link
Member

benjamn commented May 11, 2020

Yes, ApolloCache#performTransaction is the way to go here, if you need it. Wanting to delay/batch cache broadcasts is a relatively advanced use case, compared to the overwhelmingly common/default goal of wanting cache updates to be automatically broadcast to the client.

@jamshally
Copy link
Author

@benjamn - OK, thanks. Until AC3 v3.0.0-beta.39 ApolloCache.writeFragment did not trigger broadcasts to the client. However, it now does. Could you clarify if this is a bug, or as intended (and the way it will stay)?

As a data-point, there is at least some expectation in the community that ApolloCache.writeFragment does not trigger broadcast, whereas ApolloClient.writeFragment does: https://spectrum.chat/apollo/apollo-client/apolloclient-vs-apolloclient-cache-methods~3ef19a32-73cd-4a1a-b944-50b1d0a41391

Personally, I think I prefer the consistency of having ApolloClient and ApolloCache related methods work the same way.

@benjamn
Copy link
Member

benjamn commented May 11, 2020

ApolloCache.writeFragment did not trigger broadcasts to the client. However, it now does. Could you clarify if this is a bug, or as intended (and the way it will stay)?

You're right about the nature of the change (and thank you for making sure we knew about the difference), but this change was very much intentional, because it supports the general narrative that any updates to the cache should trigger corresponding updates in the UI.

We are considering adding a broadcast: boolean (default true) option to writeQuery and writeFragment to allow silencing the broadcast for individual writes. I think this option would serve the use cases that the client/cache distinction used to serve, without requiring any special understanding of the difference between cache.writeQuery and client.writeQuery. Thoughts?

@bwhitty
Copy link
Contributor

bwhitty commented May 11, 2020

Big +1 to a programmatic API to control broadcasts, as this is a needed feature for us as well.

I think it makes a lot of sense to not have an implicit difference between client.write* and cache.write* as it pertains to broadcasts, so the explicit ability to control that would be great.

Also, @benjamn you mention the cache.performTransaction API; how do you see the importance of / support for that API in a future where broadcast: false exists?

@jamshally
Copy link
Author

@benjamn - OK, thanks for the clarification.

We are considering adding a broadcast: boolean (default true) option to writeQuery and writeFragment to allow silencing the broadcast for individual writes. I think this option would serve the use cases that the client/cache distinction used to serve, without requiring any special understanding of the difference between cache.writeQuery and client.writeQuery. Thoughts?

Yes, would welcome this addition!

@hwillson hwillson added this to the Release 3.0 milestone May 12, 2020
@jamshally
Copy link
Author

My primary question has been answered, and it looks like the feature to add a broadcast boolean to cache.write* and client.write* has been added to the roadmap (+1). Closing ticket.

@benjamn
Copy link
Member

benjamn commented May 15, 2020

Opened PR #6288 to implement the options.broadcast idea for cache.writeQuery, cache.writeFragment, and cache.evict.

@darkbasic
Copy link

Generally, what are the expected behavior differences between calling methods on the ApolloCache directly, and calling their counterparts via the ApolloClient (such as reads and writes), and what are the use cases for using one vs the other?

It looks like Apollo is moving towards a standardization of the client/cache behaviour (+1 for this), but that makes the previous point even more compelling: what are the use cases for using client vs cache?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants