-
Notifications
You must be signed in to change notification settings - Fork 77
Description
👋 I just came across a crash when dealing with nested coroutineBinding
and would like to know what's your view on how to solve it.
The simplest way to reproduce is to take the example from the doc and wrap one of the coroutines inside a coroutineBinding
:
suspend fun failsIn1ms(): Result<Int, String> {
delay(1000)
return Err("error")
}
suspend fun succeedIn5ms(): Result<Int, String> {
delay(5000)
return Ok(5)
}
suspend fun succeedIn5msWrapper() = coroutineBinding {
succeedIn5ms().bind()
}
fun main() {
runBlocking {
val res = coroutineBinding {
val x = async { succeedIn5msWrapper().bind() }
val y = async { failsIn1ms().bind() }
x.await() + y.await()
}
res.onSuccess {
println("success: $it")
}.onFailure {
println("failure: $it")
}
}
}
This code will crash at runtime with a NPE at this line inside coroutineBinding. I think what's happening is that failsIn1ms()
is throwing a BindCancellationException
which gets propagate to the parent which then notify its children but then succeedIn5msWrapper()
is receiving a BindCancellationException
which is from another coroutine and receiver.result!!
is null at that stage.
One way to solve it is to wrap each bind()
call with its own scope but that doesn't feel completely right as that doesn't seem a scalable solution, you can't just know how how many coroutineBinding()
nested binding there could be. Another option is to do receiver.result ?: throw ex
instead and basically saying that if result is null
then this is just another exception that doesn't belong to this coroutineBinding
.
Are there any other better solution?
Thanks!