diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt new file mode 100644 index 00000000000..140e59ae9e1 --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/ContextSafelyExceptionHandler.kt @@ -0,0 +1,44 @@ +package dev.inmo.micro_utils.coroutines + +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.coroutineContext + +typealias ExceptionHandler = suspend (Throwable) -> T + +/** + * This instance will be used in all calls of [safely] where exception handler has not been passed + */ +var defaultSafelyExceptionHandler: ExceptionHandler = { throw it } + +/** + * This instance will be used in all calls of [safelyWithoutExceptions] as an exception handler for [safely] call + */ +var defaultSafelyWithoutExceptionHandler: ExceptionHandler = { + try { + defaultSafelyExceptionHandler(it) + } catch (e: Throwable) { + // do nothing + } +} + +/** + * This key can (and will) be used to get [ContextSafelyExceptionHandler] from [coroutineContext] of suspend functions + * and in [ContextSafelyExceptionHandler] for defining of its [CoroutineContext.Element.key] + * + * @see safelyWithContextExceptionHandler + * @see ContextSafelyExceptionHandler + */ +object ContextSafelyExceptionHandlerKey : CoroutineContext.Key + +/** + * [ExceptionHandler] wrapper which was created to make possible to use [handler] across all coroutines calls + * + * @see safelyWithContextExceptionHandler + * @see ContextSafelyExceptionHandlerKey + */ +class ContextSafelyExceptionHandler( + val handler: ExceptionHandler +) : CoroutineContext.Element { + override val key: CoroutineContext.Key<*> + get() = ContextSafelyExceptionHandlerKey +} \ No newline at end of file diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt index 33449ca5071..bf104ceaf6c 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/HandleSafely.kt @@ -4,46 +4,17 @@ import kotlinx.coroutines.* import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext -typealias ExceptionHandler = suspend (Throwable) -> T - /** - * This instance will be used in all calls of [safely] where exception handler has not been passed - */ -var defaultSafelyExceptionHandler: ExceptionHandler = { throw it } - -/** - * This instance will be used in all calls of [safelyWithoutExceptions] as an exception handler for [safely] call - */ -var defaultSafelyWithoutExceptionHandler: ExceptionHandler = { - try { - defaultSafelyExceptionHandler(it) - } catch (e: Throwable) { - // do nothing - } -} - -/** - * This key can (and will) be used to get [ContextSafelyExceptionHandler] from [coroutineContext] of suspend functions - * and in [ContextSafelyExceptionHandler] for defining of its [CoroutineContext.Element.key] + * Launching [block] in [runCatching]. In case of failure, it will: * - * @see safelyWithContextExceptionHandler - * @see ContextSafelyExceptionHandler - */ -object ContextSafelyExceptionHandlerKey : CoroutineContext.Key - -/** - * [ExceptionHandler] wrapper which was created to make possible to use [handler] across all coroutines calls + * * Try to get [ContextSafelyExceptionHandler] from current [coroutineContext] and call its + * [ContextSafelyExceptionHandler.handler] invoke. **Thrown exception from its handler + * will pass out of [runCatchingSafely]** + * * Execute [onException] inside of new [runCatching] and return its result. Throws exception + * will be caught by [runCatching] and wrapped in [Result] * - * @see safelyWithContextExceptionHandler - * @see ContextSafelyExceptionHandlerKey + * @return [Result] with result of [block] if no exceptions or [Result] from [onException] execution */ -class ContextSafelyExceptionHandler( - val handler: ExceptionHandler -) : CoroutineContext.Element { - override val key: CoroutineContext.Key<*> - get() = ContextSafelyExceptionHandlerKey -} - suspend inline fun runCatchingSafely( onException: ExceptionHandler, block: suspend () -> T @@ -58,10 +29,20 @@ suspend inline fun runCatchingSafely( } } +/** + * Launching [runCatchingSafely] with [defaultSafelyExceptionHandler] as `onException` parameter + */ suspend inline fun runCatchingSafely( block: suspend () -> T ): Result = runCatchingSafely(defaultSafelyExceptionHandler, block) +//suspend inline fun T.runCatchingSafely( +// onException: ExceptionHandler, +// block: suspend T.() -> R +//): Result = runCatchingSafely(onException) { +// block() +//} + /** * @return [ContextSafelyExceptionHandler] from [coroutineContext] by key [ContextSafelyExceptionHandlerKey] if * exists @@ -96,23 +77,9 @@ suspend fun safelyWithContextExceptionHandler( } /** - * It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions + * Calls [runCatchingSafely] and getting the result via [Result.getOrThrow] * - * Priorities of [ExceptionHandler]s: - * - * * [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 + * @see runCatchingSafely */ suspend inline fun safely( onException: ExceptionHandler, @@ -120,44 +87,19 @@ suspend inline fun safely( ): T = runCatchingSafely(onException, block).getOrThrow() /** - * It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions + * Calls [safely] with passing of [defaultSafelyExceptionHandler] as `onException` * - * Priorities of [ExceptionHandler]s: - * - * * [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 + * @see runCatchingSafely */ suspend inline fun safely( block: suspend () -> T ): T = safely(defaultSafelyExceptionHandler, block) -suspend fun T.runCatchingSafely( - onException: ExceptionHandler = defaultSafelyExceptionHandler, - block: suspend T.() -> R -): Result = runCatching { - safely(onException) { block() } -} - @Deprecated("Renamed", ReplaceWith("runCatchingSafely(block)", "dev.inmo.micro_utils.coroutines.runCatchingSafely")) suspend fun safelyWithResult( block: suspend () -> T ): Result = runCatchingSafely(defaultSafelyExceptionHandler, block) -suspend fun T.safelyWithResult( - block: suspend T.() -> R -): Result = runCatchingSafely(defaultSafelyExceptionHandler, block) - /** * Use this handler in cases you wish to include handling of exceptions by [defaultSafelyWithoutExceptionHandler] and * returning null at one time