Skip to content

Commit

Permalink
newSuspendedTransaction often doesn't honor TransactionManager.defaul…
Browse files Browse the repository at this point in the history
…tDatabase changes JetBrains#1342
  • Loading branch information
Tapac authored and SchweinchenFuntik committed Oct 23, 2021
1 parent ccb63d6 commit 00a8e85
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ interface TransactionManager {
fun bindTransactionToThread(transaction: Transaction?)

companion object {
private val currentDefaultDatabase = AtomicReference<Database>()
internal val currentDefaultDatabase = AtomicReference<Database>()

var defaultDatabase: Database?
get() = currentDefaultDatabase.get() ?: databases.firstOrNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private suspend fun <T> withTransactionScope(
): T {
val currentScope = coroutineContext[TransactionScope]
suspend fun newScope(_tx: Transaction?): T {
val manager = (_tx?.db ?: db)?.transactionManager ?: TransactionManager.manager
val manager = (_tx?.db ?: db ?: TransactionManager.currentDefaultDatabase.get())?.transactionManager ?: TransactionManager.manager

val tx = lazy(LazyThreadSafetyMode.NONE) { _tx ?: manager.newTransaction(transactionIsolation ?: manager.defaultIsolationLevel) }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.exposed.sql.tests.h2

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.runBlocking
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.tests.shared.assertEqualLists
Expand All @@ -16,6 +17,7 @@ import org.jetbrains.exposed.sql.transactions.transactionManager
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.util.concurrent.Executors
import kotlin.test.assertEquals

class MultiDatabaseTest {
Expand Down Expand Up @@ -225,4 +227,57 @@ class MultiDatabaseTest {
assertEquals(TransactionManager.defaultDatabase, db2)
TransactionManager.defaultDatabase = null
}

@Test // this test always fails for one reason or another
fun `when the default database is changed, coroutines should respect that`(): Unit = runBlocking {
assertEquals("jdbc:h2:mem:db1", db1.name) // These two asserts fail sometimes for reasons that escape me
assertEquals("jdbc:h2:mem:db2", db2.name) // but if you run just these tests one at a time, they pass.
val coroutineDispatcher1 = newSingleThreadContext("first")
TransactionManager.defaultDatabase = db1
newSuspendedTransaction(coroutineDispatcher1) {
assertEquals(db1.name, TransactionManager.current().db.name) // when running all tests together, this one usually fails
TransactionManager.current().exec("SELECT 1") { rs ->
rs.next()
assertEquals(1, rs.getInt(1))
}
}
TransactionManager.defaultDatabase = db2
newSuspendedTransaction(coroutineDispatcher1) {
assertEquals(db2.name, TransactionManager.current().db.name) // fails??
TransactionManager.current().exec("SELECT 1") { rs ->
rs.next()
assertEquals(1, rs.getInt(1))
}
}
TransactionManager.defaultDatabase = null
}

@Test // If the first two assertions pass, the entire test passes
fun `when the default database is changed, threads should respect that`() {
assertEquals("jdbc:h2:mem:db1", db1.name)
assertEquals("jdbc:h2:mem:db2", db2.name)
val threadpool = Executors.newSingleThreadExecutor()
TransactionManager.defaultDatabase = db1
threadpool.submit {
transaction {
assertEquals(db1.name, TransactionManager.current().db.name)
TransactionManager.current().exec("SELECT 1") { rs ->
rs.next()
assertEquals(1, rs.getInt(1))
}
}
}
.get()
TransactionManager.defaultDatabase = db2
threadpool.submit {
transaction {
assertEquals(db2.name, TransactionManager.current().db.name)
TransactionManager.current().exec("SELECT 1") { rs ->
rs.next()
assertEquals(1, rs.getInt(1))
}
}
}.get()
TransactionManager.defaultDatabase = null
}
}

0 comments on commit 00a8e85

Please sign in to comment.