I am trying to run multiple tasks in parallel, but the tasks are independent so if one of children coroutine fails, I do not want its siblings or parent to fail too. In the code below I have used coroutineScope to create a new scope in which these tasks run and launched 5 async tasks each on sending its id and the delay time it should wait. The second coroutine throws an exception. In this case the code does what i want it to do, it calculates the sum of the jobs that successfully finished and the ones that failed return 0.
However, I am reading that there is also supervisorScope in the kotlinx library which should be preferred instead of coroutineScope (which cancels parent/siblings if exception is not handled) for tasks are not dependent on others. I am not sure why I should be changing to use supervisorScope as I am getting the result I want with coroutineScope.
Q1: If i were to change to supervisorScope should something change in my async blocks?
Q2: Is it accepted to catch any exception inside the async block and dont let anything be propagated to its parent? I know you can also catch exceptions during .await() phase but is that the way it should be done?
runBlocking {
coroutineScope {
val job1 = async<Int> {
try {
request(1, 1000)
} catch (e: Exception) {
println("Job 1 failed with $e")
0
}
}
val job2 = async<Int> {
try {
request(2, 2000)
throw Exception("cancelling Job 2")
} catch (e: Exception) {
println("Job 2 failed: $e")
0
}
}
val job3 = async {
try {
request(3, 3000)
} catch (e: Exception) {
println("Job 3 failed with $e")
0
}
}
val job4 = async {
try {
request(4, 4000)
} catch (e: Exception) {
println("Job 4 failed with $e")
0
}
}
val job5 = async {
try {
request(5, 5000)
} catch (e: Exception) {
println("Job 5 failed with $e")
0
}
}
val result = job1.await() + job2.await() + job3.await() + job4.await() + job5.await()
println(result.toString())
}
println("Finished")
}
suspend fun request(id: Int, time: Long): Int {
println("Job $id started")
delay(time)
println("Job $id finished")
return id
}