I have a Generator class that, basically, generates some data, like:
interface Generator {
suspend fun generate(): String?
}
There are multiple implementations. Some of them may throw exceptions and some of them may took too long to generate the data:
class Faulty : Generator {
override suspend fun generate(): String? {
println("Faulty")
throw IllegalArgumentException();
}
}
class Lingering : Generator {
override suspend fun generate(): String? {
println("Lingering")
delay(Duration.ofHours(1))
return null
}
}
But some implementations are worthy
class Good : Generator {
override suspend fun generate(): String {
println("Good")
return "Goooood"
}
}
What I need to do is to gather the data generated by a list of pre-configured generators, giving each of them a timeout for its generate and ignoring the exceptions (but logging them):
fun main() = runBlocking {
val generators = listOf(Faulty(), Lingering(), Good())
val results = supervisorScope {
generators
.map { generator ->
async(CoroutineExceptionHandler { context, exception ->
println(exception)
}) {
withTimeoutOrNull(5000) {
generator.generate()
}
}
}
.awaitAll()
.filterNotNull()
}
println(results)
}
The problem is that this code fails with exception:
Faulty
Lingering
Good
Exception in thread "main" java.lang.IllegalArgumentException
at Faulty.generate (File.kt:12)
at FileKt$main$1$results$1$1$2$1.invokeSuspend (File.kt:41)
at FileKt$main$1$results$1$1$2$1.invoke (File.kt:-1)
Why doesn't the supervisorScope catch it? What am I doing wrong?