mplain
02/19/2022, 12:02 PMobject LoggingAsyncRunner {
private val log: Logger = LoggerFactory.getLogger(this.javaClass)
fun launch(job: () -> Unit) {
CoroutineScope(Dispatchers.Default).launch {
runHandlingErrors(job)
}
}
private fun runHandlingErrors(job: () -> Unit) =
try {
job()
} catch (e: IllegalArgumentException) {
log.warn("Async job exception", e)
} catch (e: Exception) {
log.error("Async job exception", e)
}
}
this cannot handle delay
, so I change job: () -> Unit
to job: suspend CoroutineScope.() -> Unit
, and also add suspend
to fun runHandlingErrors
object LoggingAsyncRunner {
private val log: Logger = LoggerFactory.getLogger(this.javaClass)
fun launch(job: suspend CoroutineScope.() -> Unit) {
CoroutineScope(Dispatchers.Default).launch {
runHandlingErrors(job)
}
}
private suspend fun runHandlingErrors(job: suspend CoroutineScope.() -> Unit) =
try {
job(~)
} catch (e: IllegalArgumentException) {
log.warn("Async job exception", e)
} catch (e: Exception) {
log.error("Async job exception", e)
}
}
now I get an error in fun runHandlingErrors inside try block (marked with ~) saying: no value passed for parameter p1
I then add CoroutineScope receiver to fun runHandlingErrors, and I get this warning:private suspend fun runHandlingErrors(job: suspend CoroutineScope.() -> Unit) =
coroutineScope {
try {
job()
} catch (e: IllegalArgumentException) {
log.warn("Async job exception", e)
} catch (e: Exception) {
log.error("Async job exception", e)
}
}
coroutineScope {
Sam
02/19/2022, 12:06 PMCoroutineScope
receiver from your job
, so it's just:
job: suspend () -> Unit
mplain
02/19/2022, 12:06 PMSam
02/19/2022, 12:07 PMCoroutineScope
, but not bothmplain
02/19/2022, 12:07 PMSam
02/19/2022, 12:07 PMlaunch
accepts a suspend CoroutineScope.() -> Unit
is a bit of an oddity which I find it best to ignore š)mplain
02/19/2022, 12:08 PMprivate fun runHandlingErrors(job: () -> Unit) =
try {
job()
} catch (e: IllegalArgumentException) {
log.warn("Async job exception", e)
} catch (e: Exception) {
log.error("Async job exception", e)
}
and
private fun runHandlingErrors(job: () -> Unit) =
try {
job()
} catch (e: IllegalArgumentException) {
log.warn("Async job exception", e)
throw e
} catch (e: Exception) {
log.error("Async job exception", e)
throw e
}
Sam
02/19/2022, 12:16 PMlaunch
or async
will propagate upwards to the parent job, until they reach the root job (which is normally a coroutine scope).mplain
02/19/2022, 12:16 PMSam
02/19/2022, 12:19 PMasync
will return a Deferred
which you can use to see if the job threw an exception. In that case, your first example would make it always appear successful, while the second example would ensure the Deferred
also fails with the appropriate exceptionasync
still cancels its parent job too, but that doesn't affect your example)