apollographql / apollo-link-state

✨ Manage your application's state with Apollo!
MIT License
1.4k stars 100 forks source link

Caching Policies & Derived Queries #272

Open fbartho opened 6 years ago

fbartho commented 6 years ago

It would be great if apollo-link-state could declare that some or all of its resolvers need to bypass "cache-only". If you want to have your link-state queries use live data, and merge it with remote data that you want to minimize fetching, it's pretty easy to get stuck splitting your code into multiple query components with different fetchPolicies, or over-fetching for no User-interface reason.

When using apollo-link-state, it's pretty natural to want to abstract complex processes, for example: a sequence of network requests that have to occur sequentially to assemble data for another request.

Example

In our app we abstracted away a wizard flow, so that each phase in the wizard can get all the data they need with a simple identifier. -- In this case, using an ID for that drafted form + an ID for the field that the wizard is populating. The problem is that if we leave the Query marked as cache-and-network, sometimes Apollo chooses not to hit our link-state resolver.

(In my case we're also using apollo-link-rest under the hood, but I don't think this affects the problem).

Ideas

A. Add an API where any resolver can be marked with an overriding cache-policy for that segment of the response. B. Add an API where resolvers can return overriding cache-policies for data that is returned C. Add an API where resolvers return a "parameter-checksum" that can override the logic used for query-lookup in the cache. -- In my example case, the parameters to my field-lookup API are: draftId & fieldId, but the underlying Queries that were used received more parameters. -- I could have collated those underlying parameters, and used them to build this checksum instead of draftId & fieldId D. Change the resolver api so link-state resolvers always call their underlying implementations, passing them cache-data, but provide them the fetchPolicy so they can choose to return the cached data, or override it.

Technically, some of the changes for this feature-request may need to be done in apollo-link or apollo-client, but this link is the one that might be invested in driving these features forwards.

hwillson commented 6 years ago

Interesting idea @fbartho!

The problem is that if we leave the Query marked as cache-and-network, sometimes Apollo chooses not to hit our link-state resolver.

This sounds like a bug to me. Is there any chance you can put together a small repro that shows this happening?

Technically, some of the changes for this feature-request may need to be done in apollo-link or apollo-client, but this link is the one that might be invested in driving these features forwards.

Just a heads up here - we're planning on integrating apollo-link-state functionality directly into apollo-client. We haven't hashed out the exact details yet, but this is one of our main objectives for Apollo Client 3.0. This should help make it easier to troubleshoot issues like this, and build out new features that involve both core Apollo Client and local state functionality.

Thanks!

fbartho commented 6 years ago

@hwillson I haven't had a moment to make a small reproduction yet, but might later this week.

Question for you: Would you know where I could find docs on the exact semantics of cache-and-network / the other fetch policies?

frederikhors commented 6 years ago

@fbartho https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy.

I think something is broken with apollo-link-state and cache (with all policies).

fbartho commented 6 years ago

@frederikhors how do you mean? Just that it doesn't have an API that tells you the fetchPolicy that's active for a specific query?

hwillson commented 6 years ago

Thanks for the suggestions @fbartho! The upcoming link state version that's integrated into Apollo Client follows something close to your last suggestion:

Change the resolver api so link-state resolvers always call their underlying implementations, passing them cache-data, but provide them the fetchPolicy so they can choose to return the cached data, or override it.

Local resolvers are always called, and each resolver has access to the cache and Apollo Client's query / mutate functions. So within local resolvers you can manipulate the cache directly, or make external network requests, and merge in the resulting data.

KeithGillette commented 5 years ago

When I first read about local resolvers, I thought they would work like server resolvers and always be called. In our apollo-angular project, we could definitely use that functionality to add in dynamically updated client-side fields via property resolvers. How soon will the changes implementing that behavior be released, @hwillson?