Merge pull request #33 from InsanusMokrassar/0.4.14

0.4.14
This commit is contained in:
InsanusMokrassar 2020-12-22 16:00:50 +06:00 committed by GitHub
commit ecfa273a81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 26 deletions

View File

@ -1,5 +1,16 @@
# Changelog
## 0.4.14
* `Versions`:
* `Kotlin`: `1.4.20` -> `1.4.21`
* `Ktor`: `1.4.3` -> `1.5.0`
* `Klock`: `2.0.1` -> `2.0.2`
* `Coroutines`:
* Add global variable `defaultSafelyExceptionHandler`
* Add `SafelyExceptionHandlerKey` and `SafelyExceptionHandler` classes to be able to overwrite
`defaultSafelyExceptionHandler` using context of coroutine
## 0.4.13
* `Common`

View File

@ -19,7 +19,7 @@ fun <T> CoroutineScope.actor(
inline fun <T> CoroutineScope.safeActor(
channelCapacity: Int = Channel.UNLIMITED,
noinline onException: ExceptionHandler<Unit> = {},
noinline onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
crossinline block: suspend (T) -> Unit
): Channel<T> = actor(
channelCapacity

View File

@ -16,7 +16,7 @@ inline fun <T> Flow<T>.subscribe(scope: CoroutineScope, noinline block: suspend
*/
inline fun <T> Flow<T>.subscribeSafely(
scope: CoroutineScope,
noinline onException: ExceptionHandler<Unit> = { throw it },
noinline onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
noinline block: suspend (T) -> Unit
) = subscribe(scope) {
safely(onException) {

View File

@ -2,23 +2,72 @@ package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.supervisorScope
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 }
/**
* Key for [SafelyExceptionHandler] which can be used in [CoroutineContext.get] to get current default
* [SafelyExceptionHandler]
*/
class SafelyExceptionHandlerKey<T> : CoroutineContext.Key<SafelyExceptionHandler<T>>
/**
* Shortcut for creating instance of [SafelyExceptionHandlerKey]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun <T> safelyExceptionHandlerKey() = SafelyExceptionHandlerKey<T>()
/**
* Wrapper for [ExceptionHandler] which can be used in [CoroutineContext] to set local (for [CoroutineContext]) default
* [ExceptionHandler]. To get it use [CoroutineContext.get] with key [SafelyExceptionHandlerKey]
*
* @see SafelyExceptionHandlerKey
* @see ExceptionHandler
*/
class SafelyExceptionHandler<T>(
val handler: ExceptionHandler<T>
) : CoroutineContext.Element {
override val key: CoroutineContext.Key<*> = safelyExceptionHandlerKey<T>()
}
/**
* It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions
*
* Priorities of [ExceptionHandler]s:
*
* * [onException] In case if custom (will be used anyway if not [defaultSafelyExceptionHandler])
* * [CoroutineContext.get] with [SafelyExceptionHandlerKey] as key
* * [defaultSafelyExceptionHandler]
*
* @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 SafelyExceptionHandlerKey
* @see SafelyExceptionHandler
*/
suspend inline fun <T> safely(
noinline onException: ExceptionHandler<T> = { throw it },
noinline onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
noinline block: suspend CoroutineScope.() -> T
): T {
return try {
supervisorScope(block)
} catch (e: Throwable) {
onException(e)
val handler = if (onException == defaultSafelyExceptionHandler) {
coroutineContext[safelyExceptionHandlerKey<T>()] ?.handler ?: onException
} else {
onException
}
handler(e)
}
}

View File

@ -6,14 +6,14 @@ kotlin.incremental.js=true
android.useAndroidX=true
android.enableJetifier=true
kotlin_version=1.4.20
kotlin_version=1.4.21
kotlin_coroutines_version=1.4.2
kotlin_serialisation_core_version=1.0.1
kotlin_exposed_version=0.28.1
ktor_version=1.4.3
ktor_version=1.5.0
klockVersion=2.0.1
klockVersion=2.0.2
github_release_plugin_version=2.2.12
@ -40,5 +40,5 @@ dokka_version=1.4.20
# Project data
group=dev.inmo
version=0.4.13
android_code_version=17
version=0.4.14
android_code_version=18

View File

@ -25,7 +25,7 @@ inline fun <T> HttpClient.createStandardWebsocketFlow(
val producerScope = this@channelFlow
do {
val reconnect = try {
safely ({ throw it }) {
safely {
ws(correctedUrl) {
for (received in incoming) {
when (received) {

View File

@ -10,21 +10,6 @@ import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
private data class CallbackContinuationPair<T> (
val callback: suspend SQLiteDatabase.() -> T,
val continuation: Continuation<T>
) {
suspend fun SQLiteDatabase.execute() {
safely(
{
continuation.resumeWithException(it)
}
) {
continuation.resume(callback())
}
}
}
class StandardSQLHelper(
context: Context,
name: String,