apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

Added custom objectCache root in inMemoryCache

Open morrys opened this issue 5 years ago • 11 comments

Hello everybody, I would like to take advantage of release 3 to propose this PR that implements a feature that I requested here: https://github.com/apollographql/apollo-feature-requests/issues/154

This change allows you to use a custom object cache in EntityCache.Root.

My main use is in the management of the apollo cache persistence and the management of the offline application: https://github.com/morrys/wora/issues/25

But it can also be used to monitor Apollo's cache.

In the file inMemoryCache.ts the main change is this: https://github.com/apollographql/apollo-client/compare/release-3.0...morrys:154-v3-custom-object-cache?expand=1#diff-add1f566156c3d8d297056b5439e0f01R72

The PR is in draft because I would like to discuss it with you ( @hwillson, @benjamn ).

Thanks, Lorenzo

morrys avatar Nov 19 '19 17:11 morrys

Thanks for following the release and taking the initiative to propose and implement this change!

To be completely honest with you, the NormalizedCache interface methods (get, set, etc.) are still very much subject to change before we finalize 3.0, so it might be a good idea to wait until later in the release process to discuss this kind of change.

For example, we are considering changing resultCaching dependencies to use the entity ID plus a field name, rather than just the ID, so the get signature may change from get(dataId: string): StoreObject to get(dataId: string, fieldName: string): StoreValue.

Also, if you're envisioning persisting every individual read or write to IndexedDB or some similar persistent storage API, I would just note that the latency for those APIs is pretty awful (5-10ms+ for single reads), so you should really prefer to write the whole cache.toObject() state at once, periodically. Hopefully this is not news to you, but I think it's important to be aware of this unfortunate reality.

benjamn avatar Nov 20 '19 15:11 benjamn

Hi @benjamn, thanks for the quick reply.

I proposed a PR in draft because I imagined that cache management was still evolving.

You're absolutely right about the latency in interfacing with storage. This was the reason why my cache library handles reading from storage only when the application starts for state reconciliation... Gets are performed on an inmemory object, and writes are managed through the combination of queue, throttle, merge and write through multiSet & multiRemove.

Obviously in react-native contexts it is remarkably efficient (they implement multiSet / multiRemove), in web contexts the throttle value must be correctly managed (for now).

In the next versions of the library I wanted to give the opportunity to manage the storage writing in a single key (similar to cache.toObject()).

Finally, it can also be used as a simple InMemory cache using the disablePersist parameter.

For a perfect integration with Apollo it would be useful to manage all the data that guarantee the consistency of the cache, the cache data and the references to the persisted queries (rootIds), through an object like objectCache and its possible configuration.

morrys avatar Nov 20 '19 18:11 morrys

so it might be a good idea to wait until later in the release process to discuss this kind of change.

I agree, the PR has been used to inform you of this need and to give my availability to implement it.

To ask for some information do you recommend opening an issue or is there an alternative channel for the v3 release?

Anyway, I created two example projects (one with nextjs ssr & one simple web app) to test apollo-client 3.0 and integration with my libraries so If you have any doubt where I can help, let me know

morrys avatar Nov 22 '19 15:11 morrys

It would be interesting to extend this discussion with the apollo-cache-persist roadmap.

In addition to the possibility of configuring different storage, there are other configurable properties that are often useful:

  • mutateKeys: allows you to filter / modify the keys when reading / writing to storage
  • mutateValues: allows to filter / modify the values during the reading / writing in the storage
  • initialState: allows you to correctly manage the SSR
  • mergeState: asynchronous callback that allows to manage the state reconciliation between the initial state and the persisted state

morrys avatar Dec 06 '19 12:12 morrys

Codecov Report

Merging #5601 into master will increase coverage by 0.02%. The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5601      +/-   ##
==========================================
+ Coverage   95.37%   95.39%   +0.02%     
==========================================
  Files          88       89       +1     
  Lines        3653     3671      +18     
  Branches      903      905       +2     
==========================================
+ Hits         3484     3502      +18     
  Misses        146      146              
  Partials       23       23              
Impacted Files Coverage Δ
src/cache/inmemory/inMemoryCache.ts 100.00% <ø> (ø)
src/cache/inmemory/entityStore.ts 99.53% <100.00%> (+<0.01%) :arrow_up:
src/cache/inmemory/objectCache.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...0508548. Read the comment docs.

codecov[bot] avatar Apr 06 '20 17:04 codecov[bot]

Eta?

austinamorusocfc avatar Jul 15 '20 21:07 austinamorusocfc

Hi @benjamn, as for this PR in draft, now that version 3.x has been released, could you point me to some documentation that will help me better understand the new cache management?

Also, what about apollo-cache-persist do you plan to upgrade it to support apollo v3?

morrys avatar Oct 14 '20 10:10 morrys

Also, what about apollo-cache-persist do you plan to upgrade it to support apollo v3?

Apollo-cache-persist is working with Apollo v3 already. We needed to push different package as the community did not have access to the v2 package

Big topic is now support for reactive variables: https://github.com/apollographql/apollo-cache-persist/issues/361

Looking to some opinions from the core team on it as not sure if makes sense to persist them.

wtrocki avatar Oct 14 '20 10:10 wtrocki

@morrys Make sure you're using the new apollo3-cache-persist package, which has been updated to work with AC3.

benjamn avatar Oct 15 '20 18:10 benjamn

@benjamn do you still plan to include persistence at some point into Apollo-Client. Any cons about adapting persistence into the core?

wtrocki avatar Oct 15 '20 19:10 wtrocki

hi @benjamn, I have updated the PR and everything seems to work correctly, I would have some internal technical questions to ask to better understand the new cache management.

I noticed that in the sources the retain function is called https://github.com/apollographql/apollo-client/blob/release-3.3/src/cache/inmemory/writeToStore.ts#L114 but not the release function nor the function gc. Is this the intended behavior or is it evolving?

In summary, should the management of retain, release, evict and gc be implemented in the application without any automatisms present in the library?

Thanks

morrys avatar Oct 19 '20 13:10 morrys

Hey all 👋! I'm doing a bit of housekeeping on some of our older PRs/issues and noticed this PR. Since we are now well into 3.0 and this is 3 years old, I'm going to close this. Thanks for the discussion and ideas!

jerelmiller avatar Nov 28 '22 17:11 jerelmiller