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
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() }
|