Eugene Komarov
06/28/2023, 10:06 AMshareIn, SharingStarted.WhileSubscribed(0, 0) and .first() may lead to the lock?
For example, I have a class which supposes to run one updater at a time. Two clients request the same resource at once and I want to be sure that only one request will be executed. But sometimes when the second client tries to start the updater but updater already invokes emit for the first client and the flow isn't finished yet, the second client will wait first() infinitely.
Here is an example with tests.Sam
06/28/2023, 10:16 AMSam
06/28/2023, 10:17 AMasync with CoroutineStart.LAZY seems like a simpler way to get the same thing.Eugene Komarov
06/28/2023, 10:18 AMshareIn approach allows also to cancel coroutine if there are no consumers.Sam
06/28/2023, 10:21 AMSam
06/28/2023, 10:24 AMSharingStarted strategy is supposed to stop the sharing as soon as the subscribers disappear, there should be only two possible outcomes:
1. Subscriber arrives while updater.invoke() is in progress, in which case it will see the result
2. Subscriber arrives after updater.invoke() is completed, in which case the sharing was already terminated and should be started again.
It does seem like what you’re describing is an unexpected behaviour that doesn’t fit either of those two assumptions.Eugene Komarov
06/28/2023, 10:28 AMupdater.invoke() but before flow was finished.
private val value = flow<Result> {
emit(updater.invoke())
// subscriber arrives here before flow was finished
}.shareIn(
scope = updateScope,
started = SharingStarted.WhileSubscribed(
0,
0,
),
)Eugene Komarov
06/28/2023, 10:30 AMshareIn logic assumes that flow is in progress, doesn't trigger one more, but there will no be any new events from flow.Eugene Komarov
06/28/2023, 10:36 AMshareIn in a separate branch, but it looks too complex, but it works ^^Sam
06/28/2023, 10:56 AMEugene Komarov
06/28/2023, 11:08 AMSam
06/28/2023, 11:09 AMSam
06/28/2023, 11:09 AMEugene Komarov
06/28/2023, 11:13 AM