Skip to content

Commit

Permalink
fix: EXPOSED-651 Try to close connection in ThreadLocalTransactionMan…
Browse files Browse the repository at this point in the history
…ager#connectionLazy if setup fails (#2320)

* fix: EXPOSED-651 Try to close connection in ThreadLocalTransactionManager#connectionLazy if setup fails

* Add Suppress to make detekt happy
  • Loading branch information
m-burst authored Dec 5, 2024
1 parent 900343b commit a17161d
Showing 1 changed file with 28 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,25 +136,35 @@ class ThreadLocalTransactionManager(

private val connectionLazy = lazy(LazyThreadSafetyMode.NONE) {
outerTransaction?.connection ?: db.connector().apply {
setupTxConnection?.invoke(this, this@ThreadLocalTransaction) ?: run {
// The order of setters here is important.
// Transaction isolation should go first as readOnly or autoCommit can start transaction with wrong isolation level
// Some drivers start a transaction right after `setAutoCommit(false)`,
// which makes `setReadOnly` throw an exception if it is called after `setAutoCommit`
if (db.connectsViaDataSource && loadDataSourceIsolationLevel && db.dataSourceIsolationLevel == -1) {
// retrieves the setting of the datasource connection & caches it
db.dataSourceIsolationLevel = transactionIsolation
db.dataSourceReadOnly = readOnly
} else if (
!db.connectsViaDataSource ||
db.dataSourceIsolationLevel != this@ThreadLocalTransaction.transactionIsolation ||
db.dataSourceReadOnly != this@ThreadLocalTransaction.readOnly
) {
// only set the level if there is no cached datasource value or if the value differs
transactionIsolation = this@ThreadLocalTransaction.transactionIsolation
readOnly = this@ThreadLocalTransaction.readOnly
@Suppress("TooGenericExceptionCaught")
try {
setupTxConnection?.invoke(this, this@ThreadLocalTransaction) ?: run {
// The order of setters here is important.
// Transaction isolation should go first as readOnly or autoCommit can start transaction with wrong isolation level
// Some drivers start a transaction right after `setAutoCommit(false)`,
// which makes `setReadOnly` throw an exception if it is called after `setAutoCommit`
if (db.connectsViaDataSource && loadDataSourceIsolationLevel && db.dataSourceIsolationLevel == -1) {
// retrieves the setting of the datasource connection & caches it
db.dataSourceIsolationLevel = transactionIsolation
db.dataSourceReadOnly = readOnly
} else if (
!db.connectsViaDataSource ||
db.dataSourceIsolationLevel != this@ThreadLocalTransaction.transactionIsolation ||
db.dataSourceReadOnly != this@ThreadLocalTransaction.readOnly
) {
// only set the level if there is no cached datasource value or if the value differs
transactionIsolation = this@ThreadLocalTransaction.transactionIsolation
readOnly = this@ThreadLocalTransaction.readOnly
}
autoCommit = false
}
} catch (e: Exception) {
try {
close()
} catch (closeException: Exception) {
e.addSuppressed(closeException)
}
autoCommit = false
throw e
}
}
}
Expand Down

0 comments on commit a17161d

Please sign in to comment.