You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

60 lines
1.7 KiB

package net.aiterp.git.ykonsole2.infrastructure
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import net.aiterp.git.ykonsole2.InfrastructureException
import net.aiterp.git.ykonsole2.application.logging.log
import net.aiterp.git.ykonsole2.domain.models.randomId
import org.intellij.lang.annotations.Language
import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.util.concurrent.TimeUnit
import javax.sql.DataSource
import kotlin.time.Duration.Companion.minutes
fun makeDataSource(
url: String,
username: String,
password: String,
poolSize: Int = 4,
driverClassName: String? = null,
): DataSource = HikariDataSource(HikariConfig().also { cfg ->
cfg.jdbcUrl = url
cfg.username = username
cfg.password = password
cfg.poolName = "ykonsole2-pool-${randomId()}"
cfg.maximumPoolSize = poolSize
cfg.maxLifetime = 1.minutes.inWholeMilliseconds
if (driverClassName != null) {
cfg.driverClassName = driverClassName
}
})
fun <T : Any?> DataSource.withConnection(func: Connection.() -> T): T {
var health = 3
while (true) {
try {
return connection.use(func)
} catch (e: SQLException) {
health--
log.error("DB error: $e", e)
if (health <= 0) {
throw InfrastructureException(e)
}
}
log.info("Trying again")
}
}
fun <T : Any?> Connection.prepare(@Language("MySQL") sql: String, func: PreparedStatement.() -> T): T =
prepareStatement(sql).use(func)
fun <T : Any?> PreparedStatement.runQuery(func: ResultSet.() -> T): T = executeQuery().use(func)
fun ResultSet.getIntOrNull(key: String) = getInt(key).takeIf { !wasNull() }