mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-29 13:38:45 +00:00
improvements in coroutines launch safely
This commit is contained in:
parent
5e04521929
commit
5db4c5c717
@ -44,6 +44,24 @@ class ContextSafelyExceptionHandler(
|
|||||||
get() = ContextSafelyExceptionHandlerKey
|
get() = ContextSafelyExceptionHandlerKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend inline fun <T> runCatchingSafely(
|
||||||
|
onException: ExceptionHandler<T>,
|
||||||
|
block: suspend () -> T
|
||||||
|
): Result<T> {
|
||||||
|
return runCatching {
|
||||||
|
block()
|
||||||
|
}.onFailure {
|
||||||
|
coroutineContext[ContextSafelyExceptionHandlerKey] ?.handler ?.invoke(it)
|
||||||
|
return runCatching {
|
||||||
|
onException(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend inline fun <T> runCatchingSafely(
|
||||||
|
block: suspend () -> T
|
||||||
|
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return [ContextSafelyExceptionHandler] from [coroutineContext] by key [ContextSafelyExceptionHandlerKey] if
|
* @return [ContextSafelyExceptionHandler] from [coroutineContext] by key [ContextSafelyExceptionHandlerKey] if
|
||||||
* exists
|
* exists
|
||||||
@ -64,7 +82,7 @@ suspend fun contextSafelyExceptionHandler() = coroutineContext[ContextSafelyExce
|
|||||||
suspend fun <T> safelyWithContextExceptionHandler(
|
suspend fun <T> safelyWithContextExceptionHandler(
|
||||||
contextExceptionHandler: ExceptionHandler<Unit>,
|
contextExceptionHandler: ExceptionHandler<Unit>,
|
||||||
safelyExceptionHandler: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
safelyExceptionHandler: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend () -> T
|
||||||
): T {
|
): T {
|
||||||
val contextSafelyExceptionHandler = contextSafelyExceptionHandler() ?.handler ?.let { oldHandler ->
|
val contextSafelyExceptionHandler = contextSafelyExceptionHandler() ?.handler ?.let { oldHandler ->
|
||||||
ContextSafelyExceptionHandler {
|
ContextSafelyExceptionHandler {
|
||||||
@ -96,24 +114,33 @@ suspend fun <T> safelyWithContextExceptionHandler(
|
|||||||
* @see safelyWithoutExceptions
|
* @see safelyWithoutExceptions
|
||||||
* @see safelyWithContextExceptionHandler
|
* @see safelyWithContextExceptionHandler
|
||||||
*/
|
*/
|
||||||
suspend fun <T> safely(
|
suspend inline fun <T> safely(
|
||||||
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<T>,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend () -> T
|
||||||
): T {
|
): T = runCatchingSafely(onException, block).getOrThrow()
|
||||||
return try {
|
|
||||||
supervisorScope(block)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
coroutineContext[ContextSafelyExceptionHandlerKey] ?.handler ?.invoke(e)
|
|
||||||
onException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <T> runCatchingSafely(
|
/**
|
||||||
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
* It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions
|
||||||
block: suspend CoroutineScope.() -> T
|
*
|
||||||
): Result<T> = runCatching {
|
* Priorities of [ExceptionHandler]s:
|
||||||
safely(onException, block)
|
*
|
||||||
}
|
* * [onException] In case if custom (will be used anyway if not [defaultSafelyExceptionHandler])
|
||||||
|
* * [CoroutineContext.get] with [SafelyExceptionHandlerKey] as key
|
||||||
|
* * [defaultSafelyExceptionHandler]
|
||||||
|
*
|
||||||
|
* Remember, that [ExceptionHandler] from [CoroutineContext.get] will be used anyway if it is available. After it will
|
||||||
|
* be called [onException]
|
||||||
|
*
|
||||||
|
* @param [onException] Will be called when happen exception inside of [block]. By default will throw exception - this
|
||||||
|
* exception will be available for catching
|
||||||
|
*
|
||||||
|
* @see defaultSafelyExceptionHandler
|
||||||
|
* @see safelyWithoutExceptions
|
||||||
|
* @see safelyWithContextExceptionHandler
|
||||||
|
*/
|
||||||
|
suspend inline fun <T> safely(
|
||||||
|
block: suspend () -> T
|
||||||
|
): T = safely(defaultSafelyExceptionHandler, block)
|
||||||
|
|
||||||
suspend fun <T, R> T.runCatchingSafely(
|
suspend fun <T, R> T.runCatchingSafely(
|
||||||
onException: ExceptionHandler<R> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<R> = defaultSafelyExceptionHandler,
|
||||||
@ -122,8 +149,9 @@ suspend fun <T, R> T.runCatchingSafely(
|
|||||||
safely(onException) { block() }
|
safely(onException) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Renamed", ReplaceWith("runCatchingSafely(block)", "dev.inmo.micro_utils.coroutines.runCatchingSafely"))
|
||||||
suspend fun <T> safelyWithResult(
|
suspend fun <T> safelyWithResult(
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend () -> T
|
||||||
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
||||||
|
|
||||||
suspend fun <T, R> T.safelyWithResult(
|
suspend fun <T, R> T.safelyWithResult(
|
||||||
@ -148,18 +176,20 @@ val defaultSafelyWithoutExceptionHandlerWithNull: ExceptionHandler<Nothing?> = {
|
|||||||
* result from exception (instead of throwing it, by default always returns null)
|
* result from exception (instead of throwing it, by default always returns null)
|
||||||
*/
|
*/
|
||||||
suspend fun <T> safelyWithoutExceptions(
|
suspend fun <T> safelyWithoutExceptions(
|
||||||
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend () -> T
|
||||||
): T? = safely(onException, block)
|
): T? = runCatchingSafely(onException, block).getOrNull()
|
||||||
|
|
||||||
suspend fun <T> runCatchingSafelyWithoutExceptions(
|
suspend fun <T> runCatchingSafelyWithoutExceptions(
|
||||||
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyExceptionHandler,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend () -> T
|
||||||
): Result<T?> = runCatching {
|
): Result<T?> = runCatchingSafely(onException, block).let {
|
||||||
safelyWithoutExceptions(onException, block)
|
if (it.isFailure) return Result.success<T?>(null)
|
||||||
|
|
||||||
|
it
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CoroutineScope(
|
fun CoroutineScopeWithDefaultFallback(
|
||||||
context: CoroutineContext,
|
context: CoroutineContext,
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>
|
defaultExceptionsHandler: ExceptionHandler<Unit>
|
||||||
) = CoroutineScope(
|
) = CoroutineScope(
|
||||||
|
@ -10,7 +10,7 @@ fun CoroutineScope.launchSafely(
|
|||||||
onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
||||||
block: suspend CoroutineScope.() -> Unit
|
block: suspend CoroutineScope.() -> Unit
|
||||||
) = launch(context, start) {
|
) = launch(context, start) {
|
||||||
safely(onException, block)
|
runCatchingSafely(onException) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CoroutineScope.launchSafelyWithoutExceptions(
|
fun CoroutineScope.launchSafelyWithoutExceptions(
|
||||||
@ -19,7 +19,7 @@ fun CoroutineScope.launchSafelyWithoutExceptions(
|
|||||||
onException: ExceptionHandler<Unit?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<Unit?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
block: suspend CoroutineScope.() -> Unit
|
block: suspend CoroutineScope.() -> Unit
|
||||||
) = launch(context, start) {
|
) = launch(context, start) {
|
||||||
safelyWithoutExceptions(onException, block)
|
runCatchingSafelyWithoutExceptions(onException) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> CoroutineScope.asyncSafely(
|
fun <T> CoroutineScope.asyncSafely(
|
||||||
@ -28,7 +28,7 @@ fun <T> CoroutineScope.asyncSafely(
|
|||||||
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
) = async(context, start) {
|
) = async(context, start) {
|
||||||
safely(onException, block)
|
runCatchingSafely(onException) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> CoroutineScope.asyncSafelyWithoutExceptions(
|
fun <T> CoroutineScope.asyncSafelyWithoutExceptions(
|
||||||
@ -37,5 +37,5 @@ fun <T> CoroutineScope.asyncSafelyWithoutExceptions(
|
|||||||
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
) = async(context, start) {
|
) = async(context, start) {
|
||||||
safelyWithoutExceptions(onException, block)
|
runCatchingSafelyWithoutExceptions(onException) { block() }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user