Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions library/failure/api/failure-library.api
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,12 @@ public final class io/github/ustudiocompany/uframework/failure/FailureKt {
public abstract interface class io/github/ustudiocompany/uframework/failure/TypeFailure : io/github/ustudiocompany/uframework/failure/Failure {
public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String;
public static final field Companion Lio/github/ustudiocompany/uframework/failure/TypeFailure$Companion;
public static final field EXCEPTION_STACKTRACE Ljava/lang/String;
public static final field PATTERN_DETAIL_KEY Ljava/lang/String;
public abstract fun getType-uX7CcE4 ()Ljava/lang/Class;
}

public final class io/github/ustudiocompany/uframework/failure/TypeFailure$Companion {
public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String;
public static final field EXCEPTION_STACKTRACE Ljava/lang/String;
public static final field PATTERN_DETAIL_KEY Ljava/lang/String;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.github.ustudiocompany.uframework.failure

import io.github.ustudiocompany.uframework.failure.Failure.Cause
import io.github.ustudiocompany.uframework.failure.Failure.Details
import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE

public interface Failure {
/**
Expand Down Expand Up @@ -123,16 +122,13 @@ public fun Failure.fullCode(delimiter: String = "."): String =
}.toString()

/**
* Returns all details of the failure, its causes, and root exception details if it exists.
* Returns all details of the failure and its causes.
* @return the all details.
*/
public fun Failure.allDetails(): Details {
val allDetails = fold(initial = { mutableListOf<Details.Item>().apply { addAll(it.details) } }) { acc, failure ->
acc.apply { addAll(failure.details) }
}
val exception = root().exceptionOrNull()
if (exception != null)
allDetails.add(Details.Item(key = EXCEPTION_STACKTRACE, value = exception.stackTraceToString()))
return if (allDetails.isEmpty())
Details.NONE
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ public interface TypeFailure<T> : Failure {
public companion object {
public const val ACTUAL_VALUE_DETAIL_KEY: String = "actual-value"
public const val PATTERN_DETAIL_KEY: String = "pattern"
public const val EXCEPTION_STACKTRACE: String = "exception-stackTrace"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.github.ustudiocompany.uframework.failure

import io.github.ustudiocompany.uframework.failure.Failure.Cause
import io.github.ustudiocompany.uframework.failure.Failure.Details
import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE
import io.github.ustudiocompany.uframework.test.kotest.UnitTest
import io.kotest.datatest.withData
import io.kotest.matchers.collections.shouldContainOnly
Expand All @@ -15,52 +14,38 @@ internal class AllDetailsFailureTest : UnitTest() {
withData(
nameFn = { (failure, _) -> failure.toString() },
listOf(
failureRoot(code = CODE_1) to
Details.NONE,
failureRootException(details = Details.of(KEY_1 to VALUE_1)) to
Details.of(
KEY_1 to VALUE_1,
EXCEPTION_STACKTRACE to VALUE_4
),
failureChild(code = CODE_2, cause = failureRoot(code = CODE_1)) to
Details.NONE,
failureChild(
failure(code = CODE_1) to Details.NONE,
failure(code = CODE_1, details = Details.of(KEY_1 to VALUE_1)) to Details.of(KEY_1 to VALUE_1),
failure(code = CODE_2, cause = failure(code = CODE_1)) to Details.NONE,
failure(
code = CODE_2,
cause = failureRoot(CODE_1),
cause = failure(CODE_1),
details = Details.of(KEY_1 to VALUE_1)
) to
Details.of(KEY_1 to VALUE_1),
failureChild(
) to Details.of(KEY_1 to VALUE_1),
failure(
code = CODE_2,
cause = failureRoot(
cause = failure(
code = CODE_1,
details = Details.of(KEY_1 to VALUE_1)
)
) to
Details.of(KEY_1 to VALUE_1),
failureChild(
) to Details.of(KEY_1 to VALUE_1),
failure(
code = CODE_2,
cause = failureRoot(
cause = failure(
code = CODE_1,
details = Details.of(KEY_1 to VALUE_1)
),
details = Details.of(KEY_2 to VALUE_2)
) to
Details.of(KEY_1 to VALUE_1, KEY_2 to VALUE_2)
) to Details.of(KEY_1 to VALUE_1, KEY_2 to VALUE_2)
)
) { (failure, expected) ->
failure.allDetails() shouldContainOnly expected
}
}
}

private fun failureRoot(code: String, details: Details = Details.NONE): Failure =
Root(code = code, details = details)

private fun failureRootException(code: String = CODE_1, details: Details = Details.NONE): Failure =
RootException(code = code, details = details)

private fun failureChild(code: String, cause: Failure, details: Details = Details.NONE): Failure =
private fun failure(code: String, details: Details = Details.NONE): Failure = Root(code = code, details = details)
private fun failure(code: String, cause: Failure, details: Details = Details.NONE): Failure =
Child(code = code, cause = Cause.Failure(cause), details = details)

private companion object {
Expand All @@ -71,20 +56,11 @@ internal class AllDetailsFailureTest : UnitTest() {
private const val KEY_2 = "key-2"
private const val VALUE_1 = "value-1"
private const val VALUE_2 = "value-2"
private const val VALUE_3 = "value-3"
private val testException = Exception(VALUE_3)
private val VALUE_4 = testException.stackTraceToString()
}

private data class Root(
override val code: String,
override val details: Details = Details.NONE,
) : Failure

private data class RootException(
override val code: String,
override val details: Details = Details.NONE,
override val cause: Cause = Cause.Exception(testException)
override val details: Details = Details.NONE
) : Failure

private data class Child(
Expand Down
1 change: 1 addition & 0 deletions library/jdbc/core/api/jdbc-core-library.api
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ public final class io/github/ustudiocompany/uframework/jdbc/transaction/Transact
}

public final class io/github/ustudiocompany/uframework/jdbc/transaction/TransactionManagerKt {
public static final fun getLogger ()Lorg/slf4j/Logger;
public static final fun useTransaction (Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionManager;Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionIsolation;Lkotlin/jvm/functions/Function1;)Lio/github/airflux/commons/types/resultk/ResultK;
public static final fun useTransaction (Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionManager;Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionIsolation;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lio/github/airflux/commons/types/resultk/ResultK;
public static synthetic fun useTransaction$default (Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionManager;Lio/github/ustudiocompany/uframework/jdbc/transaction/TransactionIsolation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/github/airflux/commons/types/resultk/ResultK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package io.github.ustudiocompany.uframework.jdbc.transaction

import io.github.airflux.commons.types.maybe.Maybe
import io.github.airflux.commons.types.maybe.onNone
import io.github.airflux.commons.types.resultk.ResultK
import io.github.airflux.commons.types.resultk.map
import io.github.ustudiocompany.uframework.jdbc.JDBCResult
Expand All @@ -16,7 +17,6 @@ import io.github.ustudiocompany.uframework.jdbc.statement.JDBCPreparedStatementI
import io.github.ustudiocompany.uframework.jdbc.statement.JDBCStatement
import io.github.ustudiocompany.uframework.telemetry.logging.logger.slf4jextension.debug
import io.github.ustudiocompany.uframework.telemetry.logging.logger.slf4jextension.error
import io.github.ustudiocompany.uframework.telemetry.logging.logger.slf4jextension.warn
import java.sql.Connection
import java.sql.PreparedStatement
import org.slf4j.LoggerFactory
Expand All @@ -30,34 +30,35 @@ internal class TransactionInstance(
override val connection: JDBCConnection
get() = this

override fun commit(): Maybe<JDBCError> = Maybe.catch(
catch = { exception ->
val errorDescription = "Error while committing transaction."
logger.error { errorDescription }
JDBCError(description = errorDescription, exception = exception)
},
block = { unwrappedConnection.commit() }
)
override fun commit(): Maybe<JDBCError> {
logger.debug("Commit transaction started.")
return Maybe.catch(
block = { unwrappedConnection.commit() },
catch = { exception ->
JDBCError(description = "Error while committing transaction.", exception = exception)
}
).onNone { logger.debug("Commit transaction finished.") }
}

override fun rollback(): Maybe<JDBCError> = Maybe.catch(
catch = { exception ->
val errorDescription = "Error while rolling back transaction."
logger.error { errorDescription }
JDBCError(description = errorDescription, exception = exception)
},
block = {
logger.warn { "Transaction would be rolled back." }
unwrappedConnection.rollback()
}
)
override fun rollback(): Maybe<JDBCError> {
logger.debug("Rollback transaction started.")
return Maybe.catch(
block = { unwrappedConnection.rollback() },
catch = { exception ->
JDBCError(description = "Error while rolling back transaction.", exception = exception)
}
).onNone { logger.debug("Rollback transaction finished.") }
}

override fun close() {
logger.debug("Closing transaction connection.")
try {
if (!unwrappedConnection.isClosed)
unwrappedConnection.close()
} catch (_: Exception) {
// ignore
} catch (expected: Exception) {
logger.error(expected) { "Error occurred while closing connection." }
}
logger.debug("Transaction connection closed.")
}

override fun preparedStatement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import io.github.ustudiocompany.uframework.jdbc.JDBCResult
import io.github.ustudiocompany.uframework.jdbc.connection.JDBCConnection
import io.github.ustudiocompany.uframework.jdbc.error.JDBCError
import io.github.ustudiocompany.uframework.jdbc.use
import io.github.ustudiocompany.uframework.telemetry.logging.logger.slf4jextension.debug
import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
* A transaction manager that provides a way to start a transaction.
Expand Down Expand Up @@ -100,6 +103,8 @@ public interface TransactionManager {
): JDBCResult<Transaction>
}

public val logger: Logger = LoggerFactory.getLogger(TransactionManager::class.java)

public inline fun <ValueT, ErrorT : Any> TransactionManager.useTransaction(
isolation: TransactionIsolation = TransactionIsolation.READ_COMMITTED,
block: (JDBCConnection) -> TransactionResult<ValueT, ErrorT, JDBCError>
Expand All @@ -114,6 +119,7 @@ public inline fun <ValueT, ErrorT : Any, ExceptionT : Any> TransactionManager.us
startTransaction(isolation)
.mapFailure { fail -> exceptionBuilder(fail) }
.use { tx ->
logger.debug { "Transaction started." }
val result = try {
block(tx.connection)
} catch (expected: Exception) {
Expand All @@ -127,8 +133,9 @@ public inline fun <ValueT, ErrorT : Any, ExceptionT : Any> TransactionManager.us
onNone = { result },
onSome = { error -> exceptionBuilder(error).asException().asFailure() }
)
else {
else
tx.rollback()
result
}

logger.debug { "Transaction ended." }
result
}
Loading