Hello everyone. Is there a way to throw an excepti...
# flow
o
Hello everyone. Is there a way to throw an exception in a
flow {}
block form another function? What I'm trying to do is this:
Copy code
private val scope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>)
private val exceptionFlow = MutableSharedFlow<Throwable>()

fun initFlow(scope: CoroutineScope) = flow {
    scope.launch { 
        exceptionFlow.collect {
            print("throwing")
            throw it //throw here to trigger retry
        }
    }

    emit(1)
    delay(2000L)
    emit(2)
}.retry(2) { cause ->
    println("retrying cause: $cause")

    true
}.catch {
    println("caught $it")
    emit(3)
}

suspend fun retry(throwable: Throwable) {
    exceptionFlow.emit(throwable)
}
    
fun main() {
    runBlocking {
        initFlow(scope).collect {
            println(it)
        }
        
        delay(500L)
        
        retry(IllegalStateException("error"))
    }
}
This prints
Copy code
1
2
throwing
the exception is not caught and the app doesn't crash. Why doesn't it work and what's the best way to implement something like this?
f
The exception you are throwing is on the scope you create (
scope
) and not on the flow of initFlow. Use coroutineScope instead
Copy code
fun initFlow(scope: CoroutineScope) = flow {
    coroutineScope { 
        launch {
            exceptionFlow.collect {
                print("throwing")
                throw it //throw here to trigger retry
            }
        }
        emit(1)
        delay(2000L)
        emit(2)
    }
}
a
Are you just trying to make sure the flow retries? Can you just use this? https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/retry.html
o
I also thought the same that there was something wrong with the coroutine scopes but I couldn't find a solution. Thanks @franztesca but I received an
Evaluation stopped while it's taking too long️
error on kotlin playground. It hangs somewhere. Here is my playground link https://pl.kotl.in/_Ye9vwIhP
f
https://pl.kotl.in/fnBz4h6he The retry is going to collect the shared flow multiple times, so you need a replay cache of at least 1 if you want your second retry to happen Also you need to collect the flow (initFlow().collect) and emit on separate coroutines, because otherwise you never get to emit (since the collection of the flow suspends forever)
o
thanks again @franztesca. it worked on this playground but there was a point I missed. flow block might also throw exception. I think that causes the collectors to cancel, and I can't collect exceptionFlow anymore. https://pl.kotl.in/NPIN3j5HU So second error cannot trigger the retry
hi again @franztesca , I moved this question to stackoverflow. exceptionHandler was a good way to handle the situation but when the outer flow completes, inner one doesn't collect anymore. I couldn't solve that yet