Skip to content

Commit 3a045eb

Browse files
authored
Emit a cache miss + stale when field's age can't be computed (#350)
1 parent 2f5a33d commit 3a045eb

3 files changed

Lines changed: 42 additions & 4 deletions

File tree

normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/CacheResolver.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,15 @@ class CacheControlCacheResolver(
256256
}
257257
if (staleDuration >= 0) isStale = true
258258
}
259+
260+
if (receivedDate == null && expirationDate == null) {
261+
// We can't determine the field's staleness: consider it stale
262+
throw CacheMissException(
263+
key = context.parentKey.keyToString(),
264+
fieldName = context.getFieldKey(),
265+
stale = true,
266+
)
267+
}
259268
}
260269

261270
val value = delegateResolver.resolveField(context)

tests/cache-control/src/commonTest/kotlin/StaleTest.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.apollographql.cache.normalized.storeReceivedDate
2222
import com.apollographql.mockserver.MockResponse
2323
import com.apollographql.mockserver.MockServer
2424
import declarative.GetUserNameQuery
25+
import declarative.cache.Cache.cache
2526
import kotlinx.coroutines.flow.Flow
2627
import kotlinx.coroutines.test.runTest
2728
import kotlin.test.Test
@@ -97,4 +98,34 @@ class StaleTest {
9798
awaitComplete()
9899
}
99100
}
101+
102+
@Test
103+
fun unknownAgeConsideredStale() = runTest {
104+
val apolloClient = ApolloClient.Builder()
105+
.serverUrl("http://unused")
106+
.cache(MemoryCacheFactory())
107+
.build()
108+
109+
apolloClient.apolloStore.writeOperation(
110+
operation = GetUserNameQuery(),
111+
data = GetUserNameQuery.Data(
112+
GetUserNameQuery.User(
113+
__typename = "User",
114+
name = "John Doe",
115+
),
116+
),
117+
)
118+
val response = apolloClient
119+
.query(GetUserNameQuery())
120+
.fetchPolicy(FetchPolicy.CacheOnly)
121+
.execute()
122+
123+
// No stored received date, so age can't be computed -> considered stale
124+
assertIs<ApolloResponse<GetUserNameQuery.Data>>(response)
125+
assertEquals(true, response.cacheInfo?.isStale)
126+
assertNull(response.data)
127+
assertNotNull(response.exception)
128+
assertIs<CacheMissException>(response.exception)
129+
assertEquals(true, response.isFromCache)
130+
}
100131
}

tests/partial-results/src/commonTest/kotlin/test/CachePartialResultTest.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -944,8 +944,7 @@ class CachePartialResultTest {
944944
fun onErrorNullWithCatchToNull() = runTest(before = { setUp() }, after = { tearDown() }) {
945945
ApolloClient.Builder()
946946
.serverUrl(mockServer.url())
947-
.normalizedCache(MemoryCacheFactory(), cacheKeyGenerator = TypePolicyCacheKeyGenerator(Cache.typePolicies), cacheResolver = CacheControlCacheResolver(SchemaCoordinatesMaxAgeProvider(Cache.maxAges, Duration.INFINITE), FieldPolicyCacheResolver(Cache.fieldPolicies)))
948-
.storeReceivedDate(true)
947+
.normalizedCache(MemoryCacheFactory(), cacheKeyGenerator = TypePolicyCacheKeyGenerator(Cache.typePolicies), cacheResolver = FieldPolicyCacheResolver(Cache.fieldPolicies))
949948
.build()
950949
.use { apolloClient ->
951950
val cacheMissResult = apolloClient.query(GetFooQuery())
@@ -1001,8 +1000,7 @@ class CachePartialResultTest {
10011000
fun onErrorHalt() = runTest(before = { setUp() }, after = { tearDown() }) {
10021001
ApolloClient.Builder()
10031002
.serverUrl(mockServer.url())
1004-
.normalizedCache(MemoryCacheFactory(), cacheKeyGenerator = TypePolicyCacheKeyGenerator(Cache.typePolicies), cacheResolver = CacheControlCacheResolver(SchemaCoordinatesMaxAgeProvider(Cache.maxAges, Duration.INFINITE), FieldPolicyCacheResolver(Cache.fieldPolicies)))
1005-
.storeReceivedDate(true)
1003+
.normalizedCache(MemoryCacheFactory(), cacheKeyGenerator = TypePolicyCacheKeyGenerator(Cache.typePolicies), cacheResolver = FieldPolicyCacheResolver(Cache.fieldPolicies))
10061004
.build()
10071005
.use { apolloClient ->
10081006
val cacheMissResult = apolloClient.query(GetFoo2Query())

0 commit comments

Comments
 (0)