mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-06 16:49:20 +00:00
add TransactionsDSL
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
* `Coroutines`:
|
* `Coroutines`:
|
||||||
* Add extensions `SmartRWLocker.alsoWithUnlockingOnSuccessAsync` and `SmartRWLocker.alsoWithUnlockingOnSuccess`
|
* Add extensions `SmartRWLocker.alsoWithUnlockingOnSuccessAsync` and `SmartRWLocker.alsoWithUnlockingOnSuccess`
|
||||||
|
* `Transactions`:
|
||||||
|
* Add `TransactionsDSL`
|
||||||
|
|
||||||
## 0.25.2
|
## 0.25.2
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ rootProject.name='micro_utils'
|
|||||||
String[] includes = [
|
String[] includes = [
|
||||||
":common",
|
":common",
|
||||||
":common:compose",
|
":common:compose",
|
||||||
|
":transactions",
|
||||||
":matrix",
|
":matrix",
|
||||||
":safe_wrapper",
|
":safe_wrapper",
|
||||||
":crypto",
|
":crypto",
|
||||||
|
7
transactions/build.gradle
Normal file
7
transactions/build.gradle
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
id "com.android.library"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64Project"
|
82
transactions/src/commonMain/kotlin/TransactionsDSL.kt
Normal file
82
transactions/src/commonMain/kotlin/TransactionsDSL.kt
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package dev.inmo.micro_utils.transactions
|
||||||
|
|
||||||
|
typealias TransactionDSLRollbackLambda = suspend (Throwable) -> Unit
|
||||||
|
class TransactionsDSL internal constructor() {
|
||||||
|
internal val rollbackActions = LinkedHashSet<TransactionDSLRollbackLambda>()
|
||||||
|
|
||||||
|
internal fun addRollbackAction(rollbackAction: TransactionDSLRollbackLambda) {
|
||||||
|
rollbackActions.add(rollbackAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class RollbackContext<T> internal constructor (
|
||||||
|
val actionResult: T,
|
||||||
|
val error: Throwable
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls [action] and, if it succeeded - saving [rollback] action for future usage for cases when some other
|
||||||
|
* action or even main one throwing an error
|
||||||
|
*
|
||||||
|
* @param rollback Will be called if
|
||||||
|
*/
|
||||||
|
suspend fun <T> TransactionsDSL.rollbackableOperation(
|
||||||
|
rollback: suspend RollbackContext<T>.() -> Unit,
|
||||||
|
action: suspend () -> T
|
||||||
|
): T {
|
||||||
|
return runCatching { action() }
|
||||||
|
.onSuccess {
|
||||||
|
addRollbackAction { e ->
|
||||||
|
val context = RollbackContext(it, e)
|
||||||
|
context.rollback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.getOrThrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts transaction with opportunity to add actions [rollbackableOperation]. How to use:
|
||||||
|
*
|
||||||
|
* ```kotlin
|
||||||
|
* doSuspendTransaction {
|
||||||
|
* println("start of action")
|
||||||
|
*
|
||||||
|
* withRollback({ // it - result of action
|
||||||
|
* // some rollback action
|
||||||
|
* }) {
|
||||||
|
* // Some action with rollback
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* withRollback({
|
||||||
|
* repository.delete(it) // it - result of createSomething, if it completes successfully
|
||||||
|
* }) {
|
||||||
|
* repository.createSomething()
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* withRollback({
|
||||||
|
* // will not be triggered due to error in action
|
||||||
|
* }) {
|
||||||
|
* error("It is just a simple error") // Will trigger rolling back previously successfully completed actions
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param onRollbackStepError Will be called if rollback action throwing some error
|
||||||
|
*/
|
||||||
|
suspend fun <T> doSuspendTransaction(
|
||||||
|
onRollbackStepError: suspend (TransactionDSLRollbackLambda, Throwable) -> Unit = { _, _ -> },
|
||||||
|
block: suspend TransactionsDSL.() -> T
|
||||||
|
): Result<T> {
|
||||||
|
val transactionsDSL = TransactionsDSL()
|
||||||
|
|
||||||
|
return runCatching {
|
||||||
|
transactionsDSL.block()
|
||||||
|
}.onFailure { e ->
|
||||||
|
transactionsDSL.rollbackActions.forEach {
|
||||||
|
runCatching {
|
||||||
|
it.invoke(e)
|
||||||
|
}.onFailure { ee ->
|
||||||
|
onRollbackStepError(it, ee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user