I'm having fun with some async code: ```) suspend...
# coroutines
r
I'm having fun with some async code:
Copy code
)
suspend fun detectTVOnSignal(tvState: MutableStateFlow<TVState>): TurnedOnDetectionHeuristics? {
    val result =  coroutineScope {
        val transientToOn = tvState.filter { it is TVState.TransientToOn }.produceIn(this)
        val on = tvState.filter { it is TVState.On }.produceIn(this)

        Timber.d { "starting select" }
        select<TurnedOnDetectionHeuristics?> {
            transientToOn.onReceive {
                Timber.d { "starting second select" }
                select {
                    on.onReceive {
                        Timber.d { "got transition and on" }
                        TurnedOnDetectionHeuristics.On
                    }
                    onTimeout(30.seconds) {
                        Timber.d { "only got transition" }
                        TurnedOnDetectionHeuristics.TransitionToOn
                    }
                }
            }
            on.onReceive {
                Timber.d { "got on" }
                TurnedOnDetectionHeuristics.On
            }
            onTimeout(30.seconds) {
                Timber.d { "timed out on on" }
                null
            }
        }
    }
    Timber.d { "Result: $result" }
    return result
}
I get: • starting select • got on <nothing> ^ I'd expect the "Result" here.
r
I assumed
select
only picks and executes the first matching clause, which is then the result
🚫 1
e
the
select
is done, but the
coroutineScope
is still alive because it has children (the launched
produceIn
jobs)
r
Oh, duh So gotta kill them first?
e
I mean this seems pretty contrived and a poor way to handle it to begin with
1
r
I'm always open to suggestions, got that one a while back
e
there's no guarantee of ordering between the two collectors. just do it once
r
That's due to domain, maybe there's a
TransientToOn
signal, maybe not.
Or maybe I don't understand what you're getting at.
e
Copy code
val onOrTransition = withTimeoutOrNull(30.seconds) {
    tvState.firstOrNull { it is TVState.On || it is TVState.TransientToOn }
}
val on = if (onOrTransition !is TVState.On) {
    withTimeoutOrNull(30.seconds) {
        tvState.firstOrNull { it is TVState.On }
    }
} else {
    onOrTransition
}
1
r
That's... way simpler. I like it.
Thank you.