For the above code I’m not sure if we have any guarantees if we get CancellationException
or fake
in both cases: when using awaitAll()
or await()
.
Please be aware there are two separate error propagation mechanisms involved in this case. There is a race between them and depending which wins, you get one exception or another. First is because we invoke await()
/awaitAll()
, so we would like to re-throw the error from the deferred. Second is because we launched that deferred as our child, and its failures automatically cancel the parent.
Using .forEach { it.await() }
doesn’t guarantee you’ll get fake
. Put a long running deferred first, then the one that fails and you will get CancellationException
. Which makes sense, because you don’t even await on the child that failed. Well, you don’t even have to await on anything - simply replace your current awaitAll()
with delay()
and you will also get CancellationException
. Maybe there is an opposite guarantee to get CancellationException
if using awaitAll()
, but my guess would be that it may throw fake
as well.
If you don’t like the behavior of errors automatically propagating from children to parent, simply use supervisorScope
. Then awaitAll()
is guaranteed to throw fake
from the above code.
Also, please be aware if you don’t plan to use the value returned from await()
/awaitAll()
, then you don’t need to even call it. coroutineScope()
automatically waits for any coroutines launched inside it. We don’t have to wait on them explicitly.