wasyl
01/26/2021, 2:14 PMmbonnin
01/26/2021, 2:39 PMwasyl
01/26/2021, 5:38 PMNETWORK_ONLY watcher was cancelled when trying to refetchdoes the first query refetch something in my repro? Or it’s just that it’s cancelled right after it emits first value that’s the issue?
mbonnin
01/26/2021, 6:38 PMIs it published somewhere?Not yet, there will be snapshots once it is merged. If you have the repo checked out locally, you can do
./gradlew publishToMavenLocal
and add mavenLocal
to your repositories to try it out.does the first query refetch something in my repro?Yea, the first query is a watcher so technically it refetches with a cache_first refetch policy but gets cancelled as soon as the network finishes because the flow gets cancelled
toFlow()
by .await()
you won't have the problemwasyl
01/26/2021, 8:47 PM.toFlow() -> .await()
fix in our codebase because abstractions, also we create watcher quite early and there’s no .await()
on that. And testing on CI would be slightly too complicated if we had to build the library locally, so we’ll have to wait for a snapshot. I could only confirm I don’t observe the issue on my repro project anymore with the snapshotmbonnin
01/26/2021, 8:49 PMwasyl
01/26/2021, 8:50 PMonCacheRecordsChanged
RealApolloStore#publish
called from somewhere else than the networkOnly watcher? I thought the issue is that cancelling the watcher also interrupts publish
callmbonnin
01/26/2021, 8:52 PMwasyl
01/26/2021, 9:02 PMApooloStore#publish
is just posted on some executor, this call is not interrupted by anything?
And the race condition is that with working case, we’d have:
• network call completes, posts runnable to publish cache changes
• watcher is canceled, unsubscribes recordChangeSubscriber
• store publishes the changes
And the not working case would be that
• network call completes, posts runnable to publish cache
• store starts publishing the changes, gets the first subscriber
• first()
cancels the flow, so the watcher is cancelled
• store calls the first subscriber’s callback but it’s already canceled and throws exception
?mbonnin
01/27/2021, 11:57 AMSeems the most recent snapshot fixes the issue for usNice glad to hear that! 🎉
Is there any release planned soon or not yet?There's not much activity in the main branch these days so releases tend to stretch a little bit. Ok if I do one on monday? I like Monday releases
wasyl
01/27/2021, 11:58 AMmbonnin
01/27/2021, 11:59 AMI just want to understand better how Apollo works internally, as it’s quite helpful sometimesSorry I missed the question above. No problem at all, brainstorming is good and we can have more people know about the internals 👍
first()
cancels the flow, so the watcher is cancelled
• the runnable is dispatched
• store calls the first subscriber’s callback but it’s already canceled and throws exception
• the second subscriber (cache_only) doesn't get the store updatewasyl
01/27/2021, 12:05 PMmbonnin
01/27/2021, 12:05 PMwasyl
01/27/2021, 12:08 PMpublish
call is just a runnable on a dispatcher, what happens with the exception? Is it thrown just to stop some potential further processing? Is it logged? Because as I understand it shouldn’t be propagated anywhere to the app codembonnin
01/27/2021, 12:09 PMSo the cancelling would’ve had to happen already after dispatching the runnable and acquiring reference to still-not-unregistered listenerRight, would need to happen somewhere here:
val recordChangeSubscriber: RecordChangeSubscriber = object : RecordChangeSubscriber {
override fun onCacheRecordsChanged(changedRecordKeys: Set<String>) {
if (dependentKeys.isEmpty() || !areDisjoint(dependentKeys, changedRecordKeys)) {
// scheduling would need to happen somewhere here
refetch()
what happens with the exceptionExcellent question, it's lost forever I'm afraid
wasyl
01/27/2021, 12:14 PMwriteToCacheAsynchronously=false
would mean that publishing is also synchronous. But it’s not, just saving to cache is synchronous, publishing the changes is notmbonnin
02/01/2021, 11:33 AM