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