mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-04 07:39:52 +00:00
add TransactionsDSL
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
* `Coroutines`:
|
||||
* Add extensions `SmartRWLocker.alsoWithUnlockingOnSuccessAsync` and `SmartRWLocker.alsoWithUnlockingOnSuccess`
|
||||
* `Transactions`:
|
||||
* Add `TransactionsDSL`
|
||||
|
||||
## 0.25.2
|
||||
|
||||
|
@@ -3,6 +3,7 @@ rootProject.name='micro_utils'
|
||||
String[] includes = [
|
||||
":common",
|
||||
":common:compose",
|
||||
":transactions",
|
||||
":matrix",
|
||||
":safe_wrapper",
|
||||
":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