apollo-kotlin icon indicating copy to clipboard operation
apollo-kotlin copied to clipboard

Query watcher re-emitting old value after caches are cleared

Open lwasyl opened this issue 4 years ago • 3 comments

I'm facing some weird behavior, which I'm not even sure if it's a bug or intended behavior. If the second, I'm curious what's the reasoning.

I have two different queries, and (probably related) each of them contains objects of the same types: QueryOne fetches [A] and [B], and QueryTwo also fetches [A] and [B]. What I'm doing then is I:

  • watch QueryOne
  • clear caches (HTTP cache and normalized cache)
  • watch QueryTwo

On the third step, when watching QueryTwo, the first watcher for QueryOne emits again, with the previous data. This is pretty unexpected, because it happens even when there are no common items between both queries. In particular it happens when all the returned lists in both queries are empty.

Is this simply lack of optimization, or a bug? Previously I expected that QueryOne might emit again if QueryTwo actually updates some object returned by QueryOne, but with empty lists I'm not so sure. Might it be because both queries return the same root, under which [A] and [B] are then nested?

Sorry for unclear example, but as usual this happens with our production schema which I'm not sure I can share :\

This is with Apollo 1.2.3

lwasyl avatar Mar 04 '20 22:03 lwasyl

Each query watchers internally builds set that called dependentKeys (com.apollographql.apollo.api.Response#dependentKeys). These are keys that will trigger any query watcher when some other query touched them

The behaviour you see is totally legit as seems like in your example QueryOne and QueryTwo have intersection of dependentKeys. Means when you trigger second query it will first fetch data from server, put to cache, and that will trigger QueryOne watcher to refetch (when query writes to cache it notifies what cache keys were modified to trigger watchers to referesh)

sav007 avatar Mar 06 '20 00:03 sav007

I expected something like this. So is this also what's happening when both queries return empty lists? Since in that case none of the returned objects (in both queries) even have an ID for the normalized cache, so I'd expect the first query to actually never emit again. Unless the top-level common object (also without an ID) triggers this new emission as well. Only if this happens, we'd be emitting unnecessarily all the time :/

lwasyl avatar Mar 06 '20 00:03 lwasyl

https://github.com/apollographql/apollo-android/blob/master/apollo-runtime/src/main/java/com/apollographql/apollo/internal/RealApolloQueryWatcher.java#L40

Yeah and this behaviour was added after fixing this issue https://github.com/apollographql/apollo-android/issues/822

sav007 avatar Mar 06 '20 22:03 sav007