package nl.astraeus.vst.base.db import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource import nl.astraeus.vst.base.Settings import java.sql.Connection import java.util.* import java.util.concurrent.atomic.AtomicBoolean val DATABASE_MIGRATIONS = arrayOf( Migration.Query( """ CREATE TABLE DATABASE_VERSION ( ID INTEGER PRIMARY KEY, QUERY TEXT, EXECUTED TIMESTAMP ) """.trimIndent() ), Migration.Query(PATCH_CREATE_QUERY), ) object Database { private var ds: HikariDataSource? = null private val currentConnection = ThreadLocal() fun start() { Class.forName("nl.astraeus.jdbc.Driver") val properties = Properties() properties["journal_mode"] = "WAL" val config = HikariConfig().apply { driverClassName = Settings.jdbcDriver jdbcUrl = Settings.jdbcConnectionUrl username = Settings.jdbcUser password = Settings.jdbcPassword maximumPoolSize = 25 isAutoCommit = false validate() } config.dataSourceProperties = properties config.addDataSourceProperty("cachePrepStmts", "true") config.addDataSourceProperty("prepStmtCacheSize", "250") config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048") ds = HikariDataSource(config) Migrations.databaseVersionTableCreated = AtomicBoolean(false) Migrations.updateDatabaseIfNeeded(DATABASE_MIGRATIONS) } private fun getConnection() = ds?.connection ?: error("Database has not been initialized!") fun transaction( block: (Connection) -> T ): T { val hasConnection = currentConnection.get() != null if (!hasConnection) { currentConnection.set(getConnection()) } val connection = currentConnection.get() try { val result = block(connection) if (!hasConnection) { connection.commit() } return result } finally { if (!hasConnection) { connection.close() currentConnection.remove() } } } }