small improvements

This commit is contained in:
InsanusMokrassar 2024-06-17 01:31:50 +06:00
parent 93b054d55e
commit a6905e73cb
2 changed files with 65 additions and 79 deletions

View File

@ -0,0 +1,44 @@
package dev.inmo.micro_utils.coroutines
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
typealias ExceptionHandler<T> = suspend (Throwable) -> T
/**
* This instance will be used in all calls of [safely] where exception handler has not been passed
*/
var defaultSafelyExceptionHandler: ExceptionHandler<Nothing> = { throw it }
/**
* This instance will be used in all calls of [safelyWithoutExceptions] as an exception handler for [safely] call
*/
var defaultSafelyWithoutExceptionHandler: ExceptionHandler<Unit> = {
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<ContextSafelyExceptionHandler>
/**
* [ExceptionHandler] wrapper which was created to make possible to use [handler] across all coroutines calls
*
* @see safelyWithContextExceptionHandler
* @see ContextSafelyExceptionHandlerKey
*/
class ContextSafelyExceptionHandler(
val handler: ExceptionHandler<Unit>
) : CoroutineContext.Element {
override val key: CoroutineContext.Key<*>
get() = ContextSafelyExceptionHandlerKey
}

View File

@ -4,46 +4,17 @@ import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
typealias ExceptionHandler<T> = suspend (Throwable) -> T
/** /**
* This instance will be used in all calls of [safely] where exception handler has not been passed * Launching [block] in [runCatching]. In case of failure, it will:
*/
var defaultSafelyExceptionHandler: ExceptionHandler<Nothing> = { throw it }
/**
* This instance will be used in all calls of [safelyWithoutExceptions] as an exception handler for [safely] call
*/
var defaultSafelyWithoutExceptionHandler: ExceptionHandler<Unit> = {
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 * * Try to get [ContextSafelyExceptionHandler] from current [coroutineContext] and call its
* @see ContextSafelyExceptionHandler * [ContextSafelyExceptionHandler.handler] invoke. **Thrown exception from its handler
*/ * will pass out of [runCatchingSafely]**
object ContextSafelyExceptionHandlerKey : CoroutineContext.Key<ContextSafelyExceptionHandler> * * Execute [onException] inside of new [runCatching] and return its result. Throws exception
* will be caught by [runCatching] and wrapped in [Result]
/**
* [ExceptionHandler] wrapper which was created to make possible to use [handler] across all coroutines calls
* *
* @see safelyWithContextExceptionHandler * @return [Result] with result of [block] if no exceptions or [Result] from [onException] execution
* @see ContextSafelyExceptionHandlerKey
*/ */
class ContextSafelyExceptionHandler(
val handler: ExceptionHandler<Unit>
) : CoroutineContext.Element {
override val key: CoroutineContext.Key<*>
get() = ContextSafelyExceptionHandlerKey
}
suspend inline fun <T> runCatchingSafely( suspend inline fun <T> runCatchingSafely(
onException: ExceptionHandler<T>, onException: ExceptionHandler<T>,
block: suspend () -> T block: suspend () -> T
@ -58,10 +29,20 @@ suspend inline fun <T> runCatchingSafely(
} }
} }
/**
* Launching [runCatchingSafely] with [defaultSafelyExceptionHandler] as `onException` parameter
*/
suspend inline fun <T> runCatchingSafely( suspend inline fun <T> runCatchingSafely(
block: suspend () -> T block: suspend () -> T
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block) ): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
//suspend inline fun <T, R> T.runCatchingSafely(
// onException: ExceptionHandler<R>,
// block: suspend T.() -> R
//): Result<R> = runCatchingSafely(onException) {
// block()
//}
/** /**
* @return [ContextSafelyExceptionHandler] from [coroutineContext] by key [ContextSafelyExceptionHandlerKey] if * @return [ContextSafelyExceptionHandler] from [coroutineContext] by key [ContextSafelyExceptionHandlerKey] if
* exists * exists
@ -96,23 +77,9 @@ suspend fun <T> 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: * @see runCatchingSafely
*
* * [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( suspend inline fun <T> safely(
onException: ExceptionHandler<T>, onException: ExceptionHandler<T>,
@ -120,44 +87,19 @@ suspend inline fun <T> safely(
): T = runCatchingSafely(onException, block).getOrThrow() ): 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: * @see runCatchingSafely
*
* * [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( suspend inline fun <T> safely(
block: suspend () -> T block: suspend () -> T
): T = safely(defaultSafelyExceptionHandler, block) ): T = safely(defaultSafelyExceptionHandler, block)
suspend fun <T, R> T.runCatchingSafely(
onException: ExceptionHandler<R> = defaultSafelyExceptionHandler,
block: suspend T.() -> R
): Result<R> = runCatching {
safely(onException) { block() }
}
@Deprecated("Renamed", ReplaceWith("runCatchingSafely(block)", "dev.inmo.micro_utils.coroutines.runCatchingSafely")) @Deprecated("Renamed", ReplaceWith("runCatchingSafely(block)", "dev.inmo.micro_utils.coroutines.runCatchingSafely"))
suspend fun <T> safelyWithResult( suspend fun <T> safelyWithResult(
block: suspend () -> T block: suspend () -> T
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block) ): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
suspend fun <T, R> T.safelyWithResult(
block: suspend T.() -> R
): Result<R> = runCatchingSafely(defaultSafelyExceptionHandler, block)
/** /**
* Use this handler in cases you wish to include handling of exceptions by [defaultSafelyWithoutExceptionHandler] and * Use this handler in cases you wish to include handling of exceptions by [defaultSafelyWithoutExceptionHandler] and
* returning null at one time * returning null at one time