You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you're targeting Android API level < 26, you'll need to enable [core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring) to support the `java.time` API:
14
+
Apollo uses OkHttp's [cacheUrlOverride](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-request/-builder/cache-url-override.html) to cache GraphQL POST requests when [persisted queries](https://www.apollographql.com/docs/kotlin/advanced/persisted-queries) and GET requests are not an option.
25
15
26
-
```kotlin
27
-
android {
28
-
compileOptions {
29
-
// Flag to enable support for the new language APIs
30
-
coreLibraryDesugaringEnabled =true
31
-
}
32
-
}
33
-
```
16
+
## Setup
34
17
35
-
Then configure your HTTP cache:
18
+
Configure your `NetworkTransport` with your cache-enabled `OkHttpClient` and `cachePostRequests` set to `true`:
Under the hood, the OkHttp `HttpEngine` uses `"${url}?variablesHash=${variables.sha256()}&operationName=${operation.name()}&operationId=${operation.id()}"` as a <code>cacheUrlOverride</code> to cache POST requests.
49
39
50
-
The HTTP cache is a Least Recently Used (LRU) cache with a configurable max size.
40
+
## Usage
51
41
52
-
Once your cache setup is complete, the cache will be used by default by all your queries. By default, queries will try to find a result in the cache first and go the network if it's not there. This is the `HttpFetchPolicy.CacheFirst` policy. You can customize that behaviour with `httpFetchPolicy(HttpFetchPolicy)`:
42
+
OkHttp uses the [cache-control header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control):
53
43
54
44
```kotlin
55
-
val response = apolloClient.query(query)
56
-
// Try the cache first - if it's a miss, try the network
57
-
.httpFetchPolicy(HttpFetchPolicy.CacheFirst)
58
-
59
-
// Only use the cache
60
-
.httpFetchPolicy(HttpFetchPolicy.CacheOnly)
61
-
62
-
// Try the network first - if there's an error, try the cache
63
-
.httpFetchPolicy(HttpFetchPolicy.NetworkFirst)
64
-
65
-
// Don't use the cache
66
-
.httpFetchPolicy(HttpFetchPolicy.NetworkOnly)
67
-
68
-
// Finally, execute your query
69
-
.execute()
45
+
val successResponse =MockResponse.Builder()
46
+
.body(FooQuery.successResponse)
47
+
.addHeader("cache-control", "max-age=100")
48
+
.build()
49
+
mockServer.enqueue(successResponse)
50
+
51
+
// first query: goes to the network and caches the response
52
+
val response1 = apolloClient.query(FooQuery()).execute()
53
+
println(response1.isFromHttpCache) // false
54
+
// second query: uses the cached response
55
+
val response2 = apolloClient.query(FooQuery()).execute()
56
+
println(response2.isFromHttpCache) // true
70
57
```
71
-
Note: mutations and subscriptions don't go through the cache.
72
58
73
-
If the query is present in cache, it will be used to return `response.data`. If not, a `HttpCacheMissException` will be thrown.
74
-
75
-
You can also set an expiration time either globally or for specific queries. The entries will automatically be removed from the cache after the expiration time:
59
+
You can use `ApolloResponse.isFromHttpCache` to determine if a given request comes from the cache:
76
60
77
61
```kotlin
78
-
// Globally
79
-
apolloClient =ApolloClient.Builder()
80
-
.httpCache(/*...*/)
81
-
// Expire after 1 hour
82
-
.httpExpireTimeout(60*60*1000)
83
-
.build()
84
-
85
-
// On a specific query
86
-
val response = apolloClient.query(query)
87
-
// Expire after 1 hour
88
-
.httpExpireTimeout(60*60*1000)
89
-
.execute()
62
+
val response = apolloClient.query(FooQuery()).execute()
63
+
assertEquals(false, response.isFromHttpCache)
90
64
```
91
65
92
-
If a specific query must not be cached, you can use `httpDoNotStore()`:
66
+
To disable caching for a particular request, use standard HTTP headers. For example, you can use `no-store` to disable storing a response:
93
67
94
68
```kotlin
95
-
val response = apolloClient.query(query)
96
-
// Don't cache this query
97
-
.httpDoNotStore(httpDoNotStore =true)
69
+
val response1 = apolloClient.query(FooQuery())
70
+
.addHttpHeader("cache-control", "no-store") // this response is not stored
71
+
.execute()
72
+
assertEquals(false, response1.isFromHttpCache)
73
+
val response2 = apolloClient.query(FooQuery()) // a new HTTP request is issued.
98
74
.execute()
75
+
assertEquals(false, response2.isFromHttpCache)
99
76
```
100
-
101
-
## Clearing the cache
102
-
103
-
Call `apolloClient.httpCache.clearAll()` to clear the cache of all entries.
Copy file name to clipboardExpand all lines: docs/source/migration/5.0.mdx
+80Lines changed: 80 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -96,3 +96,83 @@ query GetUser {
96
96
```
97
97
98
98
You can read more in the ["handling nullability" page](https://www.apollographql.com/docs/kotlin/advanced/nullability).
99
+
100
+
101
+
## `apollo-http-cache` is deprecated
102
+
103
+
Apollo Kotlin 5 removes the `apollo-http-cache` artifact. Instead, it uses the existing OkHttp cache using [cacheUrlOverride](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-request/-builder/cache-url-override.html).
The OkHttp cache uses the standard `Cache-Control` HTTP header. Compared to Apollo Kotlin 4 and `HttpFetchPolicy` the semantics are different but you can map most of the concepts:
We believe this new caching scheme is simpler and more aligned with the rest of the ecosystem, but there are important differences with the previous scheme:
174
+
175
+
- There is no equivalent to `NetworkFirst` and/or `httpExpireTimeout()`.
176
+
- The cache keys have changed, meaning your cache will be invalidated.
177
+
178
+
If either of these limitations is important for your use case, please [open an issue](https://github.com/apollographql/apollo-kotlin/issues/new).
Copy file name to clipboardExpand all lines: libraries/apollo-api/api/apollo-api.api
+14-1Lines changed: 14 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -925,9 +925,20 @@ public final class com/apollographql/apollo/api/http/ByteStringHttpBody : com/ap
925
925
public fun writeTo (Lokio/BufferedSink;)V
926
926
}
927
927
928
+
public final class com/apollographql/apollo/api/http/CacheUrlOverride : com/apollographql/apollo/api/ExecutionContext$Element {
929
+
public static final field Key Lcom/apollographql/apollo/api/http/CacheUrlOverride$Key;
930
+
public fun <init> (Ljava/lang/String;)V
931
+
public fun getKey ()Lcom/apollographql/apollo/api/ExecutionContext$Key;
932
+
public final fun getUrl ()Ljava/lang/String;
933
+
}
934
+
935
+
public final class com/apollographql/apollo/api/http/CacheUrlOverride$Key : com/apollographql/apollo/api/ExecutionContext$Key {
936
+
}
937
+
928
938
public final class com/apollographql/apollo/api/http/DefaultHttpRequestComposer : com/apollographql/apollo/api/http/HttpRequestComposer {
929
939
public static final field Companion Lcom/apollographql/apollo/api/http/DefaultHttpRequestComposer$Companion;
930
940
public fun <init> (Ljava/lang/String;)V
941
+
public fun <init> (Ljava/lang/String;Z)V
931
942
public fun compose (Lcom/apollographql/apollo/api/ApolloRequest;)Lcom/apollographql/apollo/api/http/HttpRequest;
932
943
}
933
944
@@ -1011,15 +1022,17 @@ public abstract interface class com/apollographql/apollo/api/http/HttpRequestCom
1011
1022
}
1012
1023
1013
1024
public final class com/apollographql/apollo/api/http/HttpResponse {
1014
-
public synthetic fun <init> (ILjava/util/List;Lokio/BufferedSource;Lokio/ByteString;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
1025
+
public synthetic fun <init> (ILjava/util/List;Lokio/BufferedSource;Lokio/ByteString;Lcom/apollographql/apollo/api/ExecutionContext;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
1015
1026
public final fun getBody ()Lokio/BufferedSource;
1027
+
public final fun getExecutionContext ()Lcom/apollographql/apollo/api/ExecutionContext;
1016
1028
public final fun getHeaders ()Ljava/util/List;
1017
1029
public final fun getStatusCode ()I
1018
1030
public final fun newBuilder ()Lcom/apollographql/apollo/api/http/HttpResponse$Builder;
1019
1031
}
1020
1032
1021
1033
public final class com/apollographql/apollo/api/http/HttpResponse$Builder {
1022
1034
public fun <init> (I)V
1035
+
public final fun addExecutionContext (Lcom/apollographql/apollo/api/ExecutionContext;)Lcom/apollographql/apollo/api/http/HttpResponse$Builder;
1023
1036
public final fun addHeader (Ljava/lang/String;Ljava/lang/String;)Lcom/apollographql/apollo/api/http/HttpResponse$Builder;
1024
1037
public final fun addHeaders (Ljava/util/List;)Lcom/apollographql/apollo/api/http/HttpResponse$Builder;
1025
1038
public final fun body (Lokio/BufferedSource;)Lcom/apollographql/apollo/api/http/HttpResponse$Builder;
Copy file name to clipboardExpand all lines: libraries/apollo-api/api/apollo-api.klib.api
+15Lines changed: 15 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -491,8 +491,20 @@ final class com.apollographql.apollo.api.http/ByteStringHttpBody : com.apollogra
491
491
final fun writeTo(okio/BufferedSink) // com.apollographql.apollo.api.http/ByteStringHttpBody.writeTo|writeTo(okio.BufferedSink){}[0]
492
492
}
493
493
494
+
final class com.apollographql.apollo.api.http/CacheUrlOverride : com.apollographql.apollo.api/ExecutionContext.Element { // com.apollographql.apollo.api.http/CacheUrlOverride|null[0]
final val key // com.apollographql.apollo.api.http/CacheUrlOverride.key|{}key[0]
498
+
final fun <get-key>(): com.apollographql.apollo.api/ExecutionContext.Key<*> // com.apollographql.apollo.api.http/CacheUrlOverride.key.<get-key>|<get-key>(){}[0]
499
+
final val url // com.apollographql.apollo.api.http/CacheUrlOverride.url|{}url[0]
500
+
final fun <get-url>(): kotlin/String // com.apollographql.apollo.api.http/CacheUrlOverride.url.<get-url>|<get-url>(){}[0]
501
+
502
+
final object Key : com.apollographql.apollo.api/ExecutionContext.Key<com.apollographql.apollo.api.http/CacheUrlOverride> // com.apollographql.apollo.api.http/CacheUrlOverride.Key|null[0]
503
+
}
504
+
494
505
final class com.apollographql.apollo.api.http/DefaultHttpRequestComposer : com.apollographql.apollo.api.http/HttpRequestComposer { // com.apollographql.apollo.api.http/DefaultHttpRequestComposer|null[0]
final fun <#A1: com.apollographql.apollo.api/Operation.Data> compose(com.apollographql.apollo.api/ApolloRequest<#A1>): com.apollographql.apollo.api.http/HttpRequest // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.compose|compose(com.apollographql.apollo.api.ApolloRequest<0:0>){0§<com.apollographql.apollo.api.Operation.Data>}[0]
498
510
@@ -564,6 +576,8 @@ final class com.apollographql.apollo.api.http/HttpRequest { // com.apollographql
564
576
final class com.apollographql.apollo.api.http/HttpResponse { // com.apollographql.apollo.api.http/HttpResponse|null[0]
565
577
final val body // com.apollographql.apollo.api.http/HttpResponse.body|{}body[0]
566
578
final fun <get-body>(): okio/BufferedSource? // com.apollographql.apollo.api.http/HttpResponse.body.<get-body>|<get-body>(){}[0]
579
+
final val executionContext // com.apollographql.apollo.api.http/HttpResponse.executionContext|{}executionContext[0]
580
+
final fun <get-executionContext>(): com.apollographql.apollo.api/ExecutionContext // com.apollographql.apollo.api.http/HttpResponse.executionContext.<get-executionContext>|<get-executionContext>(){}[0]
567
581
final val headers // com.apollographql.apollo.api.http/HttpResponse.headers|{}headers[0]
568
582
final fun <get-headers>(): kotlin.collections/List<com.apollographql.apollo.api.http/HttpHeader> // com.apollographql.apollo.api.http/HttpResponse.headers.<get-headers>|<get-headers>(){}[0]
569
583
final val statusCode // com.apollographql.apollo.api.http/HttpResponse.statusCode|{}statusCode[0]
@@ -577,6 +591,7 @@ final class com.apollographql.apollo.api.http/HttpResponse { // com.apollographq
577
591
final val statusCode // com.apollographql.apollo.api.http/HttpResponse.Builder.statusCode|{}statusCode[0]
578
592
final fun <get-statusCode>(): kotlin/Int // com.apollographql.apollo.api.http/HttpResponse.Builder.statusCode.<get-statusCode>|<get-statusCode>(){}[0]
579
593
594
+
final fun addExecutionContext(com.apollographql.apollo.api/ExecutionContext): com.apollographql.apollo.api.http/HttpResponse.Builder // com.apollographql.apollo.api.http/HttpResponse.Builder.addExecutionContext|addExecutionContext(com.apollographql.apollo.api.ExecutionContext){}[0]
580
595
final fun addHeader(kotlin/String, kotlin/String): com.apollographql.apollo.api.http/HttpResponse.Builder // com.apollographql.apollo.api.http/HttpResponse.Builder.addHeader|addHeader(kotlin.String;kotlin.String){}[0]
581
596
final fun addHeaders(kotlin.collections/List<com.apollographql.apollo.api.http/HttpHeader>): com.apollographql.apollo.api.http/HttpResponse.Builder // com.apollographql.apollo.api.http/HttpResponse.Builder.addHeaders|addHeaders(kotlin.collections.List<com.apollographql.apollo.api.http.HttpHeader>){}[0]
582
597
final fun body(okio/BufferedSource): com.apollographql.apollo.api.http/HttpResponse.Builder // com.apollographql.apollo.api.http/HttpResponse.Builder.body|body(okio.BufferedSource){}[0]
0 commit comments