wasyl
12/11/2020, 5:13 PMcache_only
fetch strategy, namely our Flow with that strategy fails with a network exception. Is it possible that a query with cache_only fetch strategy makes, or triggers (by refetching some previous query), a network call?mbonnin
12/11/2020, 5:14 PMwatcher
is involved somewhere?mbonnin
12/11/2020, 5:15 PMcache_only
should never reach the network but trying to understandwasyl
12/11/2020, 5:16 PMwatcher.toFlow()
somewhere deeperwasyl
12/11/2020, 5:18 PMCache_Only
strategy, and then with Network_Only
. We expect the first one to just wait until the second one fetches data and emit the same thing. However, we’re observing two network requests being madembonnin
12/11/2020, 5:18 PMfetchStrategy
was ignored because the return value was ignored (the API is a bit weird)mbonnin
12/11/2020, 5:18 PMmbonnin
12/11/2020, 5:19 PMmbonnin
12/11/2020, 5:20 PMApolloQueryCall.responseFetcher()
returns a new ApolloQueryCall
and if the return value isn't used, it's lost foreverwasyl
12/11/2020, 5:24 PMwasyl
12/11/2020, 5:29 PMmbonnin
12/11/2020, 5:29 PMmbonnin
12/11/2020, 5:30 PMwasyl
12/11/2020, 5:46 PMmbonnin
12/11/2020, 5:46 PMmbonnin
12/11/2020, 5:47 PMwasyl
12/11/2020, 5:53 PMcould it be another watcher that trigger the network call?But then should the network call be returned from the Flow started with cache_only fetch strategy?
it’s hard to keep track of who’s listening to what keyDefinitely, we already fixed a bunch of places where we didn’t request normalized cache
id
for a given type, but only in some queries. This resolved some issues and now we’re pretty sure we’re requesting all `id`s. There is another query which fetches part of the same data that the one that’s failing thoughmbonnin
12/11/2020, 5:54 PMBut then should the network call be returned from the Flow started with cache_only fetch strategy?It shouldn't. How do you know the data came from the network ?
isFromCache == false
?wasyl
12/11/2020, 5:54 PMnetwork error
mbonnin
12/11/2020, 5:54 PMmbonnin
12/11/2020, 5:55 PMmbonnin
12/11/2020, 5:55 PMwasyl
12/11/2020, 5:56 PMquery Foo {
foo { ...fooData }
bar { ...barData }
}
query Bar {
bar { ...barData }
}
Foo is started twice: with cache_only
and with network_only
strategy.
Bar is started once, with cache_and_network
.
We observe the Foo/network_only query returning successfully with data, Foo/cache_only fails with network error. We’re investigating which Bar
might be an issue now, because we do have something like 5-6 queries being made it seems 😕wasyl
12/11/2020, 5:57 PMMaybe we’re mapping to a network error for something else?Unlikely, the exception is clearly a network error, it has cause with some OkHttp type with timeout specified etc.
mbonnin
12/11/2020, 5:58 PMFoo/network_only
a watcher as well or is it one-shot?mbonnin
12/11/2020, 5:59 PMwasyl
12/11/2020, 6:03 PMIsIt’s a watcher but we terminate it immediately witha watcher as well or is it one-shot?Foo/network_only
first()
mbonnin
12/11/2020, 6:08 PMapolloClient.query(FooQuery()).responseFetcher(ApolloResponseFetchers.CACHE_ONLY).watcher().toFlow().collect {
println(it.data)
}
And this throws a ApolloNetworkException?mbonnin
12/11/2020, 6:09 PMCACHE_ONLY
stuff is pretty explicit about bypassing the networkwasyl
12/11/2020, 6:11 PMmbonnin
12/11/2020, 6:12 PMmbonnin
12/11/2020, 6:12 PMApolloServerInterceptor
therewasyl
12/11/2020, 6:14 PMCACHE_FIRST
strategy. And it’s a query for extremely simple object, no ids no nothingwasyl
12/11/2020, 6:56 PMat com.apollographql.apollo.internal.RealApolloQueryWatcher.refetch(RealApolloQueryWatcher.java:115)
at com.apollographql.apollo.internal.RealApolloQueryWatcher$1.onCacheRecordsChanged(RealApolloQueryWatcher.java:40)
at com.apollographql.apollo.internal.RealApolloStore.publish(RealApolloStore.java:117)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor$7.run(ApolloCacheInterceptor.java:218)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor.publishCacheKeys(ApolloCacheInterceptor.java:215)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor.cacheResponseAndPublishSynchronously(ApolloCacheInterceptor.java:170)
at com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor.cacheResponseAndPublish(ApolloCacheInterceptor.java:159)
specifically the chain: cacheResponseAndPublishSynchronously
-> onCacheRecordsChanged
-> refetch
mbonnin
12/12/2020, 8:52 AMCACHE_FIRST
: https://github.com/apollographql/apollo-android/blob/3e122b4ff44fff3109911dd24177a[…]a/com/apollographql/apollo/internal/RealApolloQueryWatcher.javambonnin
12/12/2020, 8:55 AMapolloClient.query(FooQuery())
.responseFetcher(ApolloResponseFetchers.CACHE_ONLY)
.watcher()
.refetchResponseFetcher(ApolloResponseFetchers.CACHE_ONLY)
.toFlow()
.collect {}
mbonnin
12/12/2020, 8:56 AMrefetchResponseFetcher
to be the same as responseFetcher
but maybe there's a reason why it's not the casewasyl
12/12/2020, 9:00 AMwasyl
12/15/2020, 6:40 PMCACHE_FIRST
refetch strategy, even if the query was specified as CACHE_ONLY
(so a cache_only queries would still make a network call on a cache miss)
• https://github.com/apollographql/apollo-android/issues/2798 — where queries that didn’t yet receive any response (CACHE_ONLY
are the easiest ones) would trigger a refetch even when a completely unrelated query populated the normalized cache
Many thanks to Martin for taking the time to figure this out! 🙂