apollographql / apollo-kotlin

:rocket:  A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
https://www.apollographql.com/docs/kotlin
MIT License
3.74k stars 653 forks source link

Normalized Cache per Fragment #1990

Open oliveeyay opened 4 years ago

oliveeyay commented 4 years ago

Hey everyone,

I was wondering if a normalized cache per GraphQL fragment was considered before? From what I've seen the normalized cache is working at the query level today. Correct me if I'm wrong!

I'm just exploring GraphQL at the moment (worked on REST and Falcor apps before). For applications that need to be performant (poor network connectivity etc...), sharing fragments' cache between queries could be a key improvement.

Example: If we take the Github example in samples, this would translate into:

Context on why I'm thinking about this: In a current app architecture using Falcor, we request for paths that resolves to what we call leafs. The logic is to:

It allows us to share leafs between screens (even between lists showing only "summary" and "detail" page if I compare to the Github example). This allows for network savings and progressive loadings.

What do you think about applying the same logic to Apollo-Android? Any pros and cons that would popup immediately?

Probably some big changes around codegen and runtime, especially if it was a new cache mode?

Thank you :)

sav007 commented 4 years ago

Very interesting approach indeed.

Not really sure if it's possible and easy to implement as it requires kinda dynamic query builders. Where the query sent to GraphQL server will be different from the user query defined in .graphql file.

It requires a lot of effort on code generation side, Apollo sends query to the server as of plain text and doesn't manipulate with the query itself. But to implement this idea we have to generate some sort of query builder.

Another question is auto persisted queries seems like won't work, probably will effect cache on the GraphQL server side as well (if query document is dynamic and constantly changes).

Another concern is data coherence / consistency, if query constructed from local and remote fragments there is no guarantee of data consistency for ANY query and this behaviour probably applicable for some specific use cases.

The question is about cost / value, is it worth the effort?

oliveeyay commented 4 years ago

Indeed it seems one of the big work would be a lot of changes on the codegen part (dynamic query builders based on fragments availability) and the runtime client as well probably.

Yeah, unfortunately auto persisted queries would be tough to handle in this mode.

Very good points about data coherence. Also I did not play with the EvictionPolicy yet. We would probably need the capability for persisted Fragments to expire in memory / disk to be coherent?

The cost vs value is indeed a great question since this project is open source. It depends mainly on how people are using Apollo-Android and how much value they would get from such a change. For the app I'm working on, 80% of the canvasses would be satisfied by the current mode (IE normalized per query), unfortunately the 20% remaining canvasses are critical paths (List -> Details -> Player for example) and we consider our current cache logic a very important piece of our infrastructure.

To be transparent, we are still at the evaluation stage and won't make a definitive choice until weeks / months. If this feature could be considered in the future, I am happy to help and work on the changes!