Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection not available after exceptions with suspendable transaction #1138

Closed
prof18 opened this issue Jan 15, 2021 · 3 comments
Closed

Connection not available after exceptions with suspendable transaction #1138

prof18 opened this issue Jan 15, 2021 · 3 comments

Comments

@prof18
Copy link

prof18 commented Jan 15, 2021

I've noticed that when an exception is thrown inside a newSuspendedTransaction, the database connection is not given back to the pool. So, after some exceptions are thrown the pool runs out of connections.

[HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - 
HikariPool-1 - Pool stats (total=3, active=3, idle=0, waiting=2)

...

org.jetbrains.exposed.exceptions.ExposedSQLException: 
java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30001ms.

Instead, if I use a transaction, everything is fine and keeps working

[HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - 
HikariPool-1 - Pool stats (total=3, active=0, idle=3, waiting=0)

It seems something similar to #1105

Here's the code:

fun Application.module(testing: Boolean = false) {
    setupDatabase()

    routing {

        get("/withTransaction") {
            transaction {
                User.new(1) {  }
            }
        }

        get("/withSuspendableTransaction") {
            newSuspendedTransaction {
                User.new(1) {  }
            }
        }
    }
}

fun setupDatabase() {
    val config = HikariConfig()
    config.driverClassName = "com.mysql.cj.jdbc.Driver"
    config.jdbcUrl = "jdbc:mysql://localhost:3307/test"
    config.username = "root"
    config.password = "password"
    config.maximumPoolSize = 3
    config.isAutoCommit = false
    config.transactionIsolation = "TRANSACTION_REPEATABLE_READ"

    // Suggestions from https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
    config.addDataSourceProperty("cachePrepStmts", "true");
    config.addDataSourceProperty("prepStmtCacheSize", "250");
    config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
    config.addDataSourceProperty("useServerPrepStmts", "true");
    config.addDataSourceProperty("useLocalSessionState", "true");
    config.addDataSourceProperty("rewriteBatchedStatements", "true");
    config.addDataSourceProperty("cacheResultSetMetadata", "true");
    config.addDataSourceProperty("cacheServerConfiguration", "true");
    config.addDataSourceProperty("elideSetAutoCommits", "true");
    config.addDataSourceProperty("maintainTimeStats", "false");

    config.validate()
    val ds = HikariDataSource(config)
    Database.connect(ds)
}

object UserTable : IntIdTable(name = "table_name")

class User(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<User>(UserTable)
}
@prof18
Copy link
Author

prof18 commented Jan 15, 2021

I've pushed a sample project that replicates the issue: https://github.com/prof18/exposed-suspendable-issue

@Tapac
Copy link
Contributor

Tapac commented Jan 17, 2021

Thank you for the sample it helps a lot. Should be fixed in master.

@Tapac Tapac closed this as completed Jan 17, 2021
@prof18
Copy link
Author

prof18 commented Jan 19, 2021

Perfect, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants