Skip to content

Commit

Permalink
Merge pull request #1842 from sideeffffect/hikari-config-backward-com…
Browse files Browse the repository at this point in the history
…patible

Ensure backward compatibility of Hikari Config
  • Loading branch information
jatcwang authored Apr 27, 2024
2 parents b6b91cb + 47fd00c commit d170c33
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 2 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ lazy val hikari = project
.settings(
name := "doobie-hikari",
description := "Hikari support for doobie.",
scalacOptions --= Seq("-Xlint:unused", "-Wunused:nowarn"),
libraryDependencies ++= Seq(
//needs to be excluded, otherwise coursier may resolve slf4j-api 2 if > Java 11
"com.zaxxer" % "HikariCP" % hikariVersion exclude("org.slf4j", "slf4j-api"),
Expand Down
130 changes: 128 additions & 2 deletions modules/hikari/src/main/scala/doobie/hikari/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,22 @@ import com.zaxxer.hikari.metrics.MetricsTrackerFactory
import doobie.enumerated.TransactionIsolation
import javax.sql.DataSource

import scala.annotation.nowarn
import scala.concurrent.duration.Duration

/** Configuration case class, susceptible to PureConfig.
* Helps with creating `com.zaxxer.hikari.HikariConfig`,
* which in turn is used to create `doobie.hikari.HikariTransactor`.
* See the method `HikariTransactor.fromConfigAutoEc` */
final case class Config(
// Whenever you add a new field to maintain backward compatibility:
// * add the field to `copy`
// * create a new `apply`
// * add a new case to `fromProduct`
//
// The default values in the constructor are not actually applied (defaults from `apply` are).
// But they still need to be present to enable tools like PureConfig.
@nowarn("msg=never used")
final case class Config private (
jdbcUrl: String,
catalog: Option[String] = None,
connectionTimeout: Duration = Duration(30, TimeUnit.SECONDS),
Expand All @@ -46,7 +55,36 @@ final case class Config(
registerMbeans: Boolean = false,
schema: Option[String] = None,
transactionIsolation: Option[TransactionIsolation] = None,
)
){
@nowarn("msg=never used")
private def copy(
jdbcUrl: String,
catalog: Option[String],
connectionTimeout: Duration,
idleTimeout: Duration,
leakDetectionThreshold: Duration,
maximumPoolSize: Int,
maxLifetime: Duration,
minimumIdle: Int,
password: Option[String],
poolName: Option[String],
username: Option[String],
validationTimeout: Duration,
allowPoolSuspension: Boolean,
autoCommit: Boolean,
connectionInitSql: Option[String],
connectionTestQuery: Option[String],
dataSourceClassName: Option[String],
dataSourceJNDI: Option[String],
driverClassName: Option[String],
initializationFailTimeout: Duration,
isolateInternalQueries: Boolean,
readOnly: Boolean,
registerMbeans: Boolean,
schema: Option[String],
transactionIsolation: Option[TransactionIsolation],
): Any = this
}

object Config {
def makeHikariConfig[F[_]](
Expand Down Expand Up @@ -103,4 +141,92 @@ object Config {
c
}

def apply(
jdbcUrl: String,
catalog: Option[String] = None,
connectionTimeout: Duration = Duration(30, TimeUnit.SECONDS),
idleTimeout: Duration = Duration(10, TimeUnit.MINUTES),
leakDetectionThreshold: Duration = Duration.Zero,
maximumPoolSize: Int = 10,
maxLifetime: Duration = Duration(30, TimeUnit.MINUTES),
minimumIdle: Int = 10,
password: Option[String] = None,
poolName: Option[String] = None,
username: Option[String] = None,
validationTimeout: Duration = Duration(5, TimeUnit.SECONDS),
allowPoolSuspension: Boolean = false,
autoCommit: Boolean = true,
connectionInitSql: Option[String] = None,
connectionTestQuery: Option[String] = None,
dataSourceClassName: Option[String] = None,
dataSourceJNDI: Option[String] = None,
driverClassName: Option[String] = None,
initializationFailTimeout: Duration = Duration(1, TimeUnit.MILLISECONDS),
isolateInternalQueries: Boolean = false,
readOnly: Boolean = false,
registerMbeans: Boolean = false,
schema: Option[String] = None,
transactionIsolation: Option[TransactionIsolation] = None,
): Config = new Config(
jdbcUrl = jdbcUrl,
catalog = catalog,
connectionTimeout = connectionTimeout,
idleTimeout = idleTimeout,
leakDetectionThreshold = leakDetectionThreshold,
maximumPoolSize = maximumPoolSize,
maxLifetime = maxLifetime,
minimumIdle = minimumIdle,
password = password,
poolName = poolName,
username = username,
validationTimeout = validationTimeout,
allowPoolSuspension = allowPoolSuspension,
autoCommit = autoCommit,
connectionInitSql = connectionInitSql,
connectionTestQuery = connectionTestQuery,
dataSourceClassName = dataSourceClassName,
dataSourceJNDI = dataSourceJNDI,
driverClassName = driverClassName,
initializationFailTimeout = initializationFailTimeout,
isolateInternalQueries = isolateInternalQueries,
readOnly = readOnly,
registerMbeans = registerMbeans,
schema = schema,
transactionIsolation = transactionIsolation
)

@nowarn
def fromProduct(p: Product): Config = p.productArity match {
case 25 =>
Config(
p.productElement(0).asInstanceOf[String],
p.productElement(1).asInstanceOf[Option[String]],
p.productElement(2).asInstanceOf[Duration],
p.productElement(3).asInstanceOf[Duration],
p.productElement(4).asInstanceOf[Duration],
p.productElement(5).asInstanceOf[Int],
p.productElement(6).asInstanceOf[Duration],
p.productElement(7).asInstanceOf[Int],
p.productElement(8).asInstanceOf[Option[String]],
p.productElement(9).asInstanceOf[Option[String]],
p.productElement(10).asInstanceOf[Option[String]],
p.productElement(11).asInstanceOf[Duration],
p.productElement(12).asInstanceOf[Boolean],
p.productElement(13).asInstanceOf[Boolean],
p.productElement(14).asInstanceOf[Option[String]],
p.productElement(15).asInstanceOf[Option[String]],
p.productElement(16).asInstanceOf[Option[String]],
p.productElement(17).asInstanceOf[Option[String]],
p.productElement(18).asInstanceOf[Option[String]],
p.productElement(19).asInstanceOf[Duration],
p.productElement(20).asInstanceOf[Boolean],
p.productElement(21).asInstanceOf[Boolean],
p.productElement(22).asInstanceOf[Boolean],
p.productElement(23).asInstanceOf[Option[String]],
p.productElement(24).asInstanceOf[Option[TransactionIsolation]],
)
}

@nowarn("msg=never used")
private def unapply(c: Config): Any = this
}

0 comments on commit d170c33

Please sign in to comment.