All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.komapper.tx.context.r2dbc.ContextualR2dbcFlowTransactionOperator.kt Maven / Gradle / Ivy

The newest version!
package org.komapper.tx.context.r2dbc

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion
import org.komapper.core.ThreadSafe
import org.komapper.tx.core.EmptyTransactionProperty
import org.komapper.tx.core.TransactionProperty

@ThreadSafe
interface ContextualR2dbcFlowTransactionOperator {
    context(R2dbcContext)
    fun  required(
        transactionProperty: TransactionProperty = EmptyTransactionProperty,
        block: suspend context(R2dbcContext)
        FlowCollector.() -> Unit,
    ): Flow

    context(R2dbcContext)
    fun  requiresNew(
        transactionProperty: TransactionProperty = EmptyTransactionProperty,
        block: suspend context(R2dbcContext)
        FlowCollector.() -> Unit,
    ): Flow

    context(R2dbcContext)
    suspend fun setRollbackOnly()

    context(R2dbcContext)
    suspend fun isRollbackOnly(): Boolean
}

internal class ContextualR2dbcFlowTransactionOperatorImpl(
    private val transactionManager: ContextualR2dbcTransactionManager,
    private val defaultTransactionProperty: TransactionProperty = EmptyTransactionProperty,
) : ContextualR2dbcFlowTransactionOperator {
    context(R2dbcContext)
    override fun  required(
        transactionProperty: TransactionProperty,
        block: suspend context(R2dbcContext)
        FlowCollector.() -> Unit,
    ): Flow {
        return flow {
            if (transactionManager.isActive()) {
                block(this@R2dbcContext, this@flow)
            } else {
                val value = executeInNewTransaction(transactionProperty, block)
                emitAll(value)
            }
        }
    }

    context(R2dbcContext)
    override fun  requiresNew(
        transactionProperty: TransactionProperty,
        block: suspend context(R2dbcContext)
        FlowCollector.() -> Unit,
    ): Flow {
        return flow {
            val value = if (transactionManager.isActive()) {
                val transactionContext = transactionManager.suspend()
                val r2dbcContext = R2dbcContext(database, transactionOperator, flowTransactionOperator, transactionContext.transaction)
                with(r2dbcContext) {
                    executeInNewTransaction(transactionProperty, block)
                }.onCompletion {
                    transactionManager.resume()
                }
            } else {
                executeInNewTransaction(transactionProperty, block)
            }
            emitAll(value)
        }
    }

    context(R2dbcContext)
    private suspend fun  executeInNewTransaction(
        transactionProperty: TransactionProperty,
        block: suspend context(R2dbcContext)
        FlowCollector.() -> Unit,
    ): Flow {
        val transactionContext = transactionManager.begin(defaultTransactionProperty + transactionProperty)
        val r2dbcContext = R2dbcContext(database, transactionOperator, flowTransactionOperator, transactionContext.transaction)
        return flow {
            with(r2dbcContext) {
                kotlin.runCatching {
                    block(this@with, this@flow)
                }.onSuccess {
                    if (transactionManager.isRollbackOnly()) {
                        transactionManager.rollback()
                    } else {
                        transactionManager.commit()
                    }
                }.onFailure { cause ->
                    kotlin.runCatching {
                        transactionManager.rollback()
                    }.onFailure {
                        cause.addSuppressed(it)
                    }
                }.getOrThrow()
            }
        }
    }

    context(R2dbcContext)
    override suspend fun setRollbackOnly() {
        transactionManager.setRollbackOnly()
    }

    context(R2dbcContext)
    override suspend fun isRollbackOnly(): Boolean {
        return transactionManager.isRollbackOnly()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy