apollo-kotlin-normalized-cache-incubating Help

Expiration

Server-controlled

When receiving a response from the server, the Cache-Control HTTP header can be used to determine the expiration date of the fields in the response.

The cache can be configured to store the expiration date of the received fields in the corresponding records. To do so, call .storeExpirationDate(true), and set your client's cache resolver to ExpirationCacheResolver:

val apolloClient = ApolloClient.builder() .serverUrl("https://example.com/graphql") .storeExpirationDate(true) .normalizedCache( normalizedCacheFactory = /*...*/, cacheResolver = ExpirationCacheResolver(), ) .build()

Expiration dates will be stored and when a field is resolved, the cache resolver will check if the field is expired. If so, it will throw a CacheMissException.

Client-controlled

When storing fields, the cache can also store their received date. This date can then be compared to the current date when resolving a field to determine if its age is above its maximum age.

To store the received date of fields, call .storeReceivedDate(true), and set your client's cache resolver to ExpirationCacheResolver:

val apolloClient = ApolloClient.builder() .serverUrl("https://example.com/graphql") .storeReceivedDate(true) .normalizedCache( normalizedCacheFactory = /*...*/, cacheResolver = ExpirationCacheResolver(maxAgeProvider), ) .build()

The maximum age of fields can be configured either programmatically, or declaratively in the schema. This is done by passing a MaxAgeProvider to the ExpirationCacheResolver.

Global max age

To set a global maximum age for all fields, pass a GlobalMaxAgeProvider to the ExpirationCacheResolver:

cacheResolver = ExpirationCacheResolver(GlobalMaxAgeProvider(1.hours)),

Max age per type and field

Programmatically

Use a SchemaCoordinatesMaxAgeProvider to specify a max age per type and/or field:

cacheResolver = ExpirationCacheResolver(SchemaCoordinatesMaxAgeProvider( maxAges = mapOf( "Query.cachedBook" to MaxAge.Duration(60.seconds), "Query.reader" to MaxAge.Duration(40.seconds), "Post" to MaxAge.Duration(4.minutes), "Book.cachedTitle" to MaxAge.Duration(30.seconds), "Reader.book" to MaxAge.Inherit, ), defaultMaxAge = 1.hours, )),

Note that this provider replicates the behavior of Apollo Server's @cacheControl directive when it comes to defaults and the meaning of Inherit.

Declaratively

To declare the maximum age of types and fields in the schema, use the @cacheControl and @cacheControlField directive:

# First import the directives extend schema @link( url: "https://specs.apollo.dev/cache/v0.1", import: ["@cacheControl", "@cacheControlField"] ) # Then extend your types extend type Query @cacheControl(maxAge: 60) @cacheControlField(name: "cachedBook", maxAge: 60) @cacheControlField(name: "reader", maxAge: 40) extend type Post @cacheControl(maxAge: 240) extend type Book @cacheControlField(name: "cachedTitle", maxAge: 30) extend type Reader @cacheControlField(name: "book", inheritMaxAge: true)

Then configure the Cache compiler plugin in your build.gradle.kts:

apollo { service("service") { packageName.set(/*...*/) plugin("com.apollographql.cache:normalized-cache-apollo-compiler-plugin:0.0.3") { argument("packageName", packageName.get()) } } }

This will generate a map in yourpackage.cache.Cache.maxAges, that you can pass to the SchemaCoordinatesMaxAgeProvider:

cacheResolver = ExpirationCacheResolver(SchemaCoordinatesMaxAgeProvider( maxAges = Cache.maxAges, defaultMaxAge = 1.hours, )),

Maximum staleness

If expired fields are acceptable up to a certain value, you can set a maximum staleness duration. This duration is the maximum time that an expired field will be resolved without resulting in a cache miss. To set this duration, call .maxStale(Duration) either globally on your client, or per operation:

client.query(MyQuery()) .fetchPolicy(FetchPolicy.CacheOnly) .maxStale(1.hours) .execute()
Last modified: 04 October 2024