[BUG] Pull to refresh causes exponential calls
Describe the bug With the implementation of store using coroutine flow and the store implementation returning store.stream(request) where the request contains a StoreRequest.fresh, we are seeing that on every pull refresh, the collect storeResponse is being called numerous times with exponential calls.
viewModelScope.launch(dispatcher) {
updateTransactions.run(params).collect {
LogHelper.d("test: refreshTransactions 3")
state.postValue(it)
}
}
In the following code above, we start a coroutine flow call with a postValue to let us know what is returned. This log helper helped us understand that every time a user pulls to refresh, this gets called with exponential growth. First pull to refresh may be 2-3 calls, then on 2nd pull to refresh 6 calls, then 10 calls. Inside of the coroutine Etc. This would also call the reader inside of the source of truth with that many times as well.
For one of our pages, we had to move away from flow to make a store.get(“key”) to fix this issue so that it would not “flicker” the ui many times which ended up crashing the app after 3-4 pull to refreshes.
To Reproduce Steps to reproduce the behavior:
- pull to refresh a page that is being viewed
Expected behavior doesn't cause exponential calls and only calls the source of truth once without having to use store.get("key") and to continue using the flow
Could you make a full reproducible sample/test that I can play with? It's unclear to me why it would go 3,6,10 refreshes, I have not seen similar and must be using differently than y'all 😁
@digitalbuddha let me see what i can do to get you a sample app. will need some time
Surely. You can take a look at tests throughout the repo. Maybe it would be easier to mutate a test to have same behavior as you.
@digitalbuddha i will give that a shot! hope to get back to you soon!
@digitalbuddha I am still going to work on a small test repo, hopefully by end of next week. however i found a workaround for the time being if you have any insight. for the viewModelScope.launch(dispatcher) {.....}, I am now assigning this job to a class variable and then calling that job.cancel() when the data comes back successfully.. This is the only way for the collect call to not exponentially grow. let me know if you have any thoughts as to why cancelling is required.
Btw I also tried to run the sample app but it was crashing upon opening.
Tough to say without knowing exactly what you are doing.
Pull latest from main branch and take a look out or sample app. Particularly the following fragment. I have not heard of reports of similar. If you can reproduce there we can fix. https://github.com/dropbox/Store/blob/main/app/src/main/java/com/dropbox/android/sample/ui/room/RoomFragment.kt
@digitalbuddha sample app now works. While i have not reproduced my exact issue on the sample app, I am curious as to why a pull to refresh causes the collect to be hit 3 times here. Those are all the calls made in just one pull to refresh. The state: refresh is coming from storeState.loading.collect {..} response

@digitalbuddha any updates on this?
@MKelman I think what you are seeing is the 3 data levels being received on the listener: the in-memory cache, the database cache and the remote data.
@MKelman Can you share the repo? Happy to take a look
we have limited our use of store and not seeing this issue anymore from probably some hacky fixes. going to close this for now