Specify cache policy for parts of a graphQL query

1.1k views Asked by At

In Apollo's GraphQL version, there are fetch policies that specify whether a fetch query should obtain data from server or use the local cache (if any data is available).

In addition, cache normalization allows usage of the cache to cut down on the amount of data that needs to be obtained from the server. For example, if I am requesting object A and object B, but earlier I had requested A and C, then in my current query it will get A from cache, and get B from server.

However, however, these specify cache policies for the entire query. I want to know if there is a method for specifying TTLs on individual fields.

From a developer standpoint, I want to be able to specify in my query that I want to go to cache for some information that I am requesting, but not others. For example, take the below query:

query PersonInfo($id: String) {
  person(id: $id) {
    birthcertificate  // Once this is cached, it is cached forever. I should just always get this info from the cache if it is available.
    age // I want to have this have a TTL of a day before invalidating the cached value and going to network
    legalName // I want to always go to network for this information. 
  }
}

In other words, for a fixed id value (and assuming this is the only query that touches the person object or its fields):

  • the first time I make this query, I get all three fields from the server.
  • now if I make this query again within a few seconds, I should only get the third field (legalName) from the server, and the first two from the cache.
  • now, if I then wait more than a day, and then make this query again, I get birthCertificate from the cache, and age + legalName from the server.

Currently, to do this the way I would want to, I end up writing three different queries, one for each TTL. Is there a better way?

Update: there is some progress on cache timing done on the iOS client (https://github.com/apollographql/apollo-ios/issues/142), but nothing specifically on this?

1

There are 1 answers

3
xadm On

It would be a nice feature but AFAIK [for now, taking js/react client, probably the same for ios]:

  • there is no query normalization, only cache normalization

  • if any of requested field not exists in cache then entire query is fetched from network

  • no time stored in cache [normalized] entries (per query/per type)

For now [only?] solution is to [save in local state/]store timestamps for each/all/some queries/responses (f.e. in onCompleted) and use it to invalidate/evict them before fetching. It could probably be automated f.e. starting timers within some field policy fn.

You can fetch person data at start (session) just after login ... any following and more granular person(id: $id) { birthcertificate } query (like in react subcomponent) can have "own" 'cache-only' policy. If you need always fresh legalName, fetch for it [separately or not] with network-only policy.