Skip to content

Commit 39c62ab

Browse files
committed
Move to 3.10.0 of base and zio. ProtoContext now in portable.
1 parent c68654b commit 39c62ab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+538
-405
lines changed

build.sbt

+6-2
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,17 @@ lazy val `quill-sql` =
109109
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
110110
"Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases"
111111
),
112+
excludeDependencies ++= Seq(
113+
"com.typesafe.scala-logging" % "scala-logging_2.13"
114+
),
112115
libraryDependencies ++= Seq(
113116
// .excludeAll(ExclusionRule(organization="com.trueaccord.scalapb")
114117
("com.lihaoyi" %% "pprint" % "0.5.6").withDottyCompat(scalaVersion.value),
115-
("io.getquill" %% "quill-core-portable" % "3.7.2").withDottyCompat(scalaVersion.value),
116-
("io.getquill" %% "quill-sql-portable" % "3.7.2").withDottyCompat(scalaVersion.value),
118+
("io.getquill" %% "quill-core-portable" % "3.10.0").withDottyCompat(scalaVersion.value),
119+
("io.getquill" %% "quill-sql-portable" % "3.10.0").withDottyCompat(scalaVersion.value),
117120
//("org.scalameta" %% "scalafmt-dynamic" % "2.7.4").withDottyCompat(scalaVersion.value),
118121
//"org.scala-lang" % "scala3-library_3.0.0-M3" % (scalaVersion.value),
122+
"com.typesafe.scala-logging" % "scala-logging_3" % "3.9.4"
119123
),
120124
// If it's a community-build we're using a scala incremental version so there's no scalatest for that
121125
libraryDependencies ++= {

quill-jdbc-zio/src/main/scala/io/getquill/ZioJdbcContexts.scala

+9-10
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ class OracleZioJdbcContext[N <: NamingStrategy](val naming: N)
3737
extends ZioJdbcContext[OracleDialect, N]
3838
with OracleJdbcRunContext[N]
3939

40-
// Probing is not supported in ProtoQuill Yet
41-
// trait WithProbing[D <: SqlIdiom, N <: NamingStrategy] extends ZioJdbcContext[D, N] {
42-
// def probingConfig: Config;
43-
// override def probingDataSource: Option[DataSource] = Some(JdbcContextConfig(probingConfig).dataSource)
44-
// }
45-
46-
// trait WithProbingPrefix[D <: SqlIdiom, N <: NamingStrategy] extends WithProbing[D, N] {
47-
// def configPrefix: String;
48-
// def probingConfig: Config = LoadConfig(configPrefix)
49-
// }
40+
trait WithProbing[D <: SqlIdiom, N <: NamingStrategy] extends ZioJdbcContext[D, N] {
41+
def probingConfig: Config;
42+
override def probingDataSource: Option[DataSource] = Some(JdbcContextConfig(probingConfig).dataSource)
43+
}
44+
45+
trait WithProbingPrefix[D <: SqlIdiom, N <: NamingStrategy] extends WithProbing[D, N] {
46+
def configPrefix: String;
47+
def probingConfig: Config = LoadConfig(configPrefix)
48+
}

quill-jdbc-zio/src/main/scala/io/getquill/context/ZioJdbc.scala

+105-90
Original file line numberDiff line numberDiff line change
@@ -2,137 +2,152 @@ package io.getquill.context
22

33
import com.typesafe.config.Config
44
import io.getquill.JdbcContextConfig
5-
import zio.{ Has, Task, ZIO, ZLayer, ZManaged }
5+
import io.getquill.context.qzio.ImplicitSyntax.Implicit
6+
import zio.{ Has, IO, Task, ZIO, ZLayer, ZManaged }
67
import zio.stream.ZStream
7-
import io.getquill.util.LoadConfig
8-
import izumi.reflect.Tag
8+
import io.getquill.util.{ ContextLogger, LoadConfig }
99

1010
import java.io.Closeable
1111
import java.sql.{ Connection, SQLException }
1212
import javax.sql.DataSource
1313

1414
object ZioJdbc {
15-
import zio.blocking._
16-
17-
/** Describes a single HOCON Jdbc Config block */
18-
case class Prefix(name: String)
19-
20-
type QIO[T] = ZIO[QConnection, SQLException, T]
21-
type QStream[T] = ZStream[Has[Connection] with Blocking, SQLException, T]
22-
type QConnection = Has[Connection] with Blocking
23-
type QDataSource = Has[DataSource with Closeable] with Blocking
15+
type QIO[T] = ZIO[Has[Connection], SQLException, T]
16+
type QStream[T] = ZStream[Has[Connection], SQLException, T]
2417

2518
object QIO {
2619
def apply[T](t: => T): QIO[T] = ZIO.effect(t).refineToOrDie[SQLException]
2720
}
2821

29-
object QDataSource {
30-
object Managed {
31-
def fromDataSource(ds: => DataSource with Closeable) =
32-
for {
33-
block <- ZManaged.environment[Blocking]
34-
managedDs <- ZManaged.fromAutoCloseable(Task(ds))
35-
} yield (Has(managedDs) ++ block)
36-
}
22+
object DataSourceLayer {
23+
def live: ZLayer[Has[DataSource with Closeable], SQLException, Has[Connection]] = layer
3724

38-
val toConnection: ZLayer[QDataSource, SQLException, QConnection] = {
25+
private[getquill] val layer = {
3926
val managed =
4027
for {
41-
fromBlocking <- ZManaged.environment[Has[DataSource with Closeable] with Blocking]
42-
from = fromBlocking.get[DataSource with Closeable]
43-
blocking = fromBlocking.get[Blocking.Service]
44-
r <- ZManaged.fromAutoCloseable(ZIO.effect(from.getConnection).refineToOrDie[SQLException]: ZIO[Any, SQLException, Connection])
45-
} yield Has(r) ++ Has(blocking)
28+
blockingExecutor <- ZIO.succeed(zio.blocking.Blocking.Service.live.blockingExecutor).toManaged_
29+
from <- ZManaged.environment[Has[DataSource with Closeable]]
30+
r <- ZioJdbc.managedBestEffort(ZIO.effect(from.get.getConnection)).refineToOrDie[SQLException].lock(blockingExecutor)
31+
} yield Has(r)
4632
ZLayer.fromManagedMany(managed)
4733
}
4834

49-
def fromDataSource(ds: => DataSource with Closeable): ZLayer[Blocking, Throwable, QDataSource] =
50-
ZLayer.fromEffectMany {
51-
for {
52-
block <- ZIO.environment[Blocking]
53-
dst <- Task(ds)
54-
} yield (Has(dst) ++ block)
55-
}
35+
def fromDataSource(ds: => DataSource with Closeable): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
36+
ZLayer.fromEffect(Task(ds))
5637

57-
def fromConfig(config: => Config): ZLayer[Blocking, Throwable, QDataSource] =
38+
def fromConfig(config: => Config): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
5839
fromJdbcConfig(JdbcContextConfig(config))
5940

60-
def fromPrefix(prefix: Prefix): ZLayer[Blocking, Throwable, QDataSource] =
61-
fromJdbcConfig(JdbcContextConfig(LoadConfig(prefix.name)))
41+
def fromPrefix(prefix: String): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
42+
fromJdbcConfig(JdbcContextConfig(LoadConfig(prefix)))
43+
44+
def fromJdbcConfig(jdbcContextConfig: => JdbcContextConfig): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
45+
ZLayer.fromManagedMany(
46+
for {
47+
conf <- ZManaged.fromEffect(Task(jdbcContextConfig))
48+
ds <- managedBestEffort(Task(conf.dataSource: DataSource with Closeable))
49+
} yield Has(ds)
50+
)
51+
}
6252

63-
def fromPrefix(prefix: String): ZLayer[Blocking, Throwable, QDataSource] =
53+
object QDataSource {
54+
object Managed {
55+
@deprecated(message = "Not needed anymore. Use: ZioJdbc.managedBestEffort(Task(ds)).map(Has(_))", "3.8.0")
56+
def fromDataSource(ds: => DataSource with Closeable) =
57+
managedBestEffort(Task(ds)).map(Has(_))
58+
}
59+
60+
@deprecated("Use DataSourceLayer.live instead", "3.8.0")
61+
val toConnection: ZLayer[Has[DataSource with Closeable], SQLException, Has[Connection]] =
62+
DataSourceLayer.live
63+
64+
@deprecated("Use ZLayer.fromEffect(Task(ds)) instead", "3.8.0")
65+
def fromDataSource(ds: => DataSource with Closeable): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
66+
ZLayer.fromEffect(Task(ds))
67+
68+
def fromConfig(config: => Config): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
69+
fromJdbcConfig(JdbcContextConfig(config))
70+
71+
def fromPrefix(prefix: String): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
6472
fromJdbcConfig(JdbcContextConfig(LoadConfig(prefix)))
6573

66-
def fromJdbcConfig(jdbcContextConfig: => JdbcContextConfig): ZLayer[Blocking, Throwable, QDataSource] =
74+
def fromJdbcConfig(jdbcContextConfig: => JdbcContextConfig): ZLayer[Any, Throwable, Has[DataSource with Closeable]] =
6775
ZLayer.fromManagedMany(
6876
for {
69-
block <- ZManaged.environment[Blocking]
7077
conf <- ZManaged.fromEffect(Task(jdbcContextConfig))
71-
ds <- ZManaged.fromAutoCloseable(Task(conf.dataSource: DataSource with Closeable))
72-
} yield (Has(ds) ++ block)
78+
ds <- managedBestEffort(Task(conf.dataSource: DataSource with Closeable))
79+
} yield Has(ds)
7380
)
7481
}
7582

76-
implicit class ZioQuillThrowableExt[T](qzio: ZIO[QConnection, Throwable, T]) {
83+
implicit class ZioQuillThrowableExt[T](qzio: ZIO[Has[Connection], Throwable, T]) {
84+
@deprecated("Use .refineToOrDie[SQLException]", "3.8.0")
7785
def justSqlEx = qzio.refineToOrDie[SQLException]
7886
}
7987

8088
object QConnection {
81-
def fromDataSource: ZLayer[QDataSource, SQLException, QConnection] = QDataSource.toConnection
82-
def dependOnDataSource[T](qzio: ZIO[QConnection, Throwable, T]) =
83-
qzio.justSqlEx.provideLayer(QDataSource.toConnection)
84-
def provideConnection[T](qzio: ZIO[QConnection, Throwable, T])(conn: Connection): ZIO[Blocking, SQLException, T] =
85-
provideOne[Connection, T, SQLException, Blocking](conn)(qzio.justSqlEx)
86-
def provideConnectionFrom[T](qzio: ZIO[QConnection, Throwable, T])(ds: DataSource with Closeable): ZIO[Blocking, SQLException, T] =
87-
provideOne[DataSource & Closeable, T, SQLException, Blocking](ds)(QConnection.dependOnDataSource(qzio.justSqlEx))
88-
}
89+
@deprecated("Use DataSourceLayer.live. If you need just SQLException add .refineToOrDie[SQLException]", "3.8.0")
90+
def fromDataSource: ZLayer[Has[DataSource with Closeable], SQLException, Has[Connection]] = DataSourceLayer.live
91+
92+
@deprecated("Use qzio.onDataSource.", "3.8.0")
93+
def dependOnDataSource[T](qzio: ZIO[Has[Connection], Throwable, T]) =
94+
qzio.onDataSource
95+
96+
@deprecated("Use qzio.provide(Has(conn)). If you need just SQLException add .refineToOrDie[SQLException]", "3.8.0")
97+
def provideConnection[T](qzio: ZIO[Has[Connection], Throwable, T])(conn: Connection): ZIO[Any, SQLException, T] =
98+
qzio.provide(Has(conn)).refineToOrDie[SQLException]
8999

90-
implicit class DataSourceCloseableExt(ds: DataSource with Closeable) {
91-
def withDefaultBlocking: QDataSource = Has(ds) ++ Has(Blocking.Service.live)
100+
@deprecated("Use qzio.onDataSource.provide(Has(ds)). If you need just SQLException add .refineToOrDie[SQLException]", "3.8.0")
101+
def provideConnectionFrom[T](qzio: ZIO[Has[Connection], Throwable, T])(ds: DataSource with Closeable): ZIO[Any, SQLException, T] =
102+
qzio.onDataSource.provide(Has(ds)).refineToOrDie[SQLException]
92103
}
93104

94-
implicit class QuillZioExt[T](qzio: ZIO[QConnection, Throwable, T]) {
95-
/**
96-
* Allows the user to specify `Has[DataSource]` instead of `Has[Connection]` for a Quill ZIO value i.e.
97-
* Converts:<br>
98-
* `ZIO[QConnection, Throwable, T]` to `ZIO[QDataSource, Throwable, T]` a.k.a.<br>
99-
* `ZIO[Has[Connection] with Blocking, Throwable, T]` to `ZIO[Has[DataSource] with Blocking, Throwable, T]` a.k.a.<br>
100-
*/
101-
def dependOnDataSource(): ZIO[QDataSource, SQLException, T] = QConnection.dependOnDataSource(qzio)
105+
implicit class QuillZioExt[T](qzio: ZIO[Has[Connection], Throwable, T]) {
106+
import io.getquill.context.qzio.ImplicitSyntax._
102107

103108
/**
104-
* Allows the user to specify JDBC `DataSource` instead of `QConnection` for a Quill ZIO value i.e.
105-
* Provides a DataSource object which internally brackets `dataSource.getConnection` and `connection.close()`.
106-
* This effectively converts:<br>
107-
* `ZIO[QConnection, Throwable, T]` to `ZIO[Blocking, Throwable, T]` a.k.a.<br>
108-
* `ZIO[Has[Connection] with Blocking, Throwable, T]` to `ZIO[Blocking, Throwable, T]` a.k.a.<br>
109+
* Change `Has[Connection]` of a QIO to `Has[DataSource with Closeable]` by providing a `DataSourceLayer.live` instance
110+
* which will grab a connection from the data-source, perform the QIO operation, and the immediately release the connection.
111+
* This is used for data-sources that have pooled connections e.g. Hikari.
112+
* {{{
113+
* def ds: DataSource with Closeable = ...
114+
* run(query[Person]).onDataSource.provide(Has(ds))
115+
* }}}
109116
*/
110-
def provideConnectionFrom(ds: DataSource with Closeable): ZIO[Blocking, SQLException, T] =
111-
QConnection.provideConnectionFrom(qzio)(ds)
117+
def onDataSource: ZIO[Has[DataSource with Closeable], SQLException, T] =
118+
qzio.provideLayer(DataSourceLayer.live).refineToOrDie[SQLException]
112119

113-
/**
114-
* Allows the user to specify JDBC `Connection` instead of `QConnection` for a Quill ZIO value i.e.
115-
* Provides a Connection object which converts:<br>
116-
* `ZIO[QConnection, Throwable, T]` to `ZIO[Blocking, Throwable, T]` a.k.a.<br>
117-
* `ZIO[Has[Connection] with Blocking, Throwable, T]` to `ZIO[Blocking, Throwable, T]` a.k.a.<br>
118-
*/
119-
def provideConnection(conn: Connection): ZIO[Blocking, SQLException, T] =
120-
QConnection.provideConnection(qzio)(conn)
120+
/** Shortcut for `onDataSource` */
121+
def onDS: ZIO[Has[DataSource with Closeable], SQLException, T] =
122+
qzio.onDataSource
123+
124+
def implicitDS(implicit implicitEnv: Implicit[Has[DataSource with Closeable]]): IO[SQLException, T] =
125+
qzio.onDataSource.implicitly
126+
127+
@deprecated("Use qzio.onDataSource.", "3.8.0")
128+
def dependOnDataSource(): ZIO[Has[DataSource with Closeable], SQLException, T] =
129+
qzio.onDataSource.refineToOrDie[SQLException]
130+
131+
@deprecated("Use qzio.onDataSource.provide(Has(ds)). If you need just SQLException add .refineToOrDie[SQLException]", "3.8.0")
132+
def provideConnectionFrom(ds: DataSource with Closeable): ZIO[Nothing, SQLException, T] =
133+
qzio.onDataSource.provide(Has(ds)).refineToOrDie[SQLException]
134+
135+
@deprecated("Use qzio.provide(Has(conn)). If you need just SQLException add .refineToOrDie[SQLException]", "3.8.0")
136+
def provideConnection(conn: Connection): ZIO[Any, SQLException, T] =
137+
qzio.provide(Has(conn)).refineToOrDie[SQLException]
121138
}
122139

123-
// TODO Rewrite with -P-in and +Pout variant
124-
// private[getquill] case class Provide[+P: Tag](provision: P):
125-
// def to[Rest <: Has[_]: Tag, T, E: Tag](qzio: ZIO[Has[P] with Rest, E, T]): ZIO[Rest, E, T] =
126-
// for {
127-
// rest <- ZIO.environment[Rest]
128-
// env = Has(provision) ++ rest
129-
// result <- qzio.provide(env)
130-
// } yield result
131-
132-
private[getquill] def provideOne[P: Tag, T, E: Tag, Rest <: Has[_]: Tag](provision: P)(qzio: ZIO[Has[P] with Rest, E, T]): ZIO[Rest, E, T] =
133-
for {
134-
rest <- ZIO.environment[Rest]
135-
env = Has(provision) ++ rest
136-
result <- qzio.provide(env)
137-
} yield result
140+
/**
141+
* This is the same as `ZManaged.fromAutoCloseable` but if the `.close()` fails it will log `"close() of resource failed"`
142+
* and continue instead of immediately throwing an error in the ZIO die-channel. That is because for JDBC purposes,
143+
* a failure on the connection close is usually a recoverable failure. In the cases where it happens it occurs
144+
* as the byproduct of a bad state (e.g. failing to close a transaction before closing the connection or failing to
145+
* release a stale connection) which will eventually cause other operations (i.e. future reads/writes) to fail
146+
* that have not occurred yet.
147+
*/
148+
def managedBestEffort[R, E, A <: AutoCloseable](effect: ZIO[R, E, A]) =
149+
ZManaged.make(effect)(resource =>
150+
ZIO.effect(resource.close()).tapError(e => ZIO.effect(logger.underlying.error(s"close() of resource failed", e)).ignore).ignore)
151+
152+
private[getquill] val logger = ContextLogger(ZioJdbc.getClass)
138153
}

0 commit comments

Comments
 (0)