diff --git a/src/main/scala/io/github/gaelrenoux/tranzactio/DatabaseModuleBase.scala b/src/main/scala/io/github/gaelrenoux/tranzactio/DatabaseModuleBase.scala index 48a4925..ab2b8cf 100644 --- a/src/main/scala/io/github/gaelrenoux/tranzactio/DatabaseModuleBase.scala +++ b/src/main/scala/io/github/gaelrenoux/tranzactio/DatabaseModuleBase.scala @@ -35,10 +35,10 @@ abstract class DatabaseModuleBase[Connection, Dbs <: DatabaseOps.ServiceOps[Conn } /** Creates a Database Layer which requires an existing ConnectionSource. */ - def fromConnectionSource: ZLayer[ConnectionSource with Blocking, Nothing, Database] + def fromConnectionSource: ZLayer[ConnectionSource with Blocking with Clock, Nothing, Database] /** Creates a Tranzactio Connection, given a JDBC connection and a Blocking. Useful for some utilities. */ - def connectionFromJdbc(env: Blocking, connection: JdbcConnection): ZIO[Any, Nothing, Connection] + def connectionFromJdbc(env: Blocking with Clock, connection: JdbcConnection): ZIO[Any, Nothing, Connection] /** Commodity method: creates a Database Layer which includes its own ConnectionSource based on a DataSource. Most * connection pool implementations should be able to provide you a DataSource. @@ -46,16 +46,16 @@ abstract class DatabaseModuleBase[Connection, Dbs <: DatabaseOps.ServiceOps[Conn * When no implicit ErrorStrategies is available, the default ErrorStrategies will be used. */ final val fromDatasource: ZLayer[Has[DataSource] with Blocking with Clock, Nothing, Database] = - (ConnectionSource.fromDatasource ++ Blocking.any) >>> fromConnectionSource + (ConnectionSource.fromDatasource ++ Blocking.any ++ Clock.any) >>> fromConnectionSource /** As `fromDatasource`, but provides a default ErrorStrategiesRef. When a method is called with no available implicit * ErrorStrategiesRef, the ErrorStrategiesRef in argument will be used. */ final def fromDatasource(errorStrategies: ErrorStrategiesRef): ZLayer[Has[DataSource] with Blocking with Clock, Nothing, Database] = - (ConnectionSource.fromDatasource(errorStrategies) ++ Blocking.any) >>> fromConnectionSource + (ConnectionSource.fromDatasource(errorStrategies) ++ Blocking.any ++ Clock.any) >>> fromConnectionSource /** As `fromDatasource(ErrorStrategiesRef)`, but an `ErrorStrategies` is provided through a layer instead of as a parameter. */ final val fromDatasourceAndErrorStrategies: ZLayer[Has[DataSource] with Has[ErrorStrategies] with Blocking with Clock, Nothing, Database] = - (ConnectionSource.fromDatasourceAndErrorStrategies ++ Blocking.any) >>> fromConnectionSource + (ConnectionSource.fromDatasourceAndErrorStrategies ++ Blocking.any ++ Clock.any) >>> fromConnectionSource val any: ZLayer[Database, Nothing, Database] = ZLayer.requires[Database] diff --git a/src/main/scala/io/github/gaelrenoux/tranzactio/anorm/package.scala b/src/main/scala/io/github/gaelrenoux/tranzactio/anorm/package.scala index 75e8d5f..1fd83f1 100644 --- a/src/main/scala/io/github/gaelrenoux/tranzactio/anorm/package.scala +++ b/src/main/scala/io/github/gaelrenoux/tranzactio/anorm/package.scala @@ -1,10 +1,10 @@ package io.github.gaelrenoux.tranzactio import java.sql.{Connection => JdbcConnection} - import io.github.gaelrenoux.tranzactio.test.DatabaseModuleTestOps import izumi.reflect.Tag import zio.blocking.{Blocking, effectBlocking} +import zio.clock.Clock import zio.{Has, ZIO, ZLayer} @@ -32,12 +32,12 @@ package object anorm extends Wrapper { private[tranzactio] override implicit val connectionTag: Tag[Connection] = anorm.connectionTag /** How to provide a Connection for the module, given a JDBC connection and some environment. */ - final def connectionFromJdbc(env: Blocking, connection: JdbcConnection): ZIO[Any, Nothing, Connection] = + final def connectionFromJdbc(env: Blocking with Clock, connection: JdbcConnection): ZIO[Any, Nothing, Connection] = ZIO.succeed(Has(connection) ++ env) /** Creates a Database Layer which requires an existing ConnectionSource. */ - final def fromConnectionSource: ZLayer[ConnectionSource with Blocking, Nothing, Database] = - ZLayer.fromFunction { env: ConnectionSource with Blocking => + final def fromConnectionSource: ZLayer[ConnectionSource with Blocking with Clock, Nothing, Database] = + ZLayer.fromFunction { env: ConnectionSource with Blocking with Clock => new DatabaseServiceBase[Connection](env.get[ConnectionSource.Service]) with Database.Service { override final def connectionFromJdbc(connection: JdbcConnection): ZIO[Any, Nothing, Connection] = self.connectionFromJdbc(env, connection) diff --git a/src/main/scala/io/github/gaelrenoux/tranzactio/doobie/package.scala b/src/main/scala/io/github/gaelrenoux/tranzactio/doobie/package.scala index 0ee31f9..d131db6 100644 --- a/src/main/scala/io/github/gaelrenoux/tranzactio/doobie/package.scala +++ b/src/main/scala/io/github/gaelrenoux/tranzactio/doobie/package.scala @@ -6,8 +6,8 @@ import cats.effect.Resource import io.github.gaelrenoux.tranzactio.test.DatabaseModuleTestOps import izumi.reflect.Tag import zio.blocking.Blocking +import zio.clock.Clock import zio.interop.catz._ -import zio.interop.catz.implicits.rts import zio.stream.ZStream import zio.stream.interop.fs2z._ import zio.{Has, Task, ZIO, ZLayer} @@ -47,17 +47,20 @@ package object doobie extends Wrapper { private[tranzactio] override implicit val connectionTag: Tag[Connection] = doobie.connectionTag /** How to provide a Connection for the module, given a JDBC connection and some environment. */ - final def connectionFromJdbc(env: Blocking, connection: JdbcConnection): ZIO[Any, Nothing, Connection] = - ZIO.effectTotal { - val connect = (c: JdbcConnection) => Resource.pure[Task, JdbcConnection](c) - val interp = KleisliInterpreter[Task].ConnectionInterpreter - val tran = Transactor(connection, connect, interp, Strategy.void) - Has(tran) - } + final def connectionFromJdbc(env: Blocking with Clock, connection: JdbcConnection): ZIO[Any, Nothing, Connection] = + ZIO.runtime[Blocking with Clock].flatMap{implicit r: zio.Runtime[Blocking with Clock] => { + ZIO.effectTotal[Connection] { + val connect = (c: JdbcConnection) => Resource.pure[Task, JdbcConnection](c) + val interp = KleisliInterpreter[Task].ConnectionInterpreter + val tran = Transactor(connection, connect, interp, Strategy.void) + Has(tran) + } + }} + .provideLayer(ZLayer.succeed(env.get[Blocking.Service]) ++ ZLayer.succeed(env.get[Clock.Service])) /** Creates a Database Layer which requires an existing ConnectionSource. */ - final def fromConnectionSource: ZLayer[ConnectionSource with Blocking, Nothing, Database] = - ZLayer.fromFunction { env: ConnectionSource with Blocking => + final def fromConnectionSource: ZLayer[ConnectionSource with Blocking with Clock, Nothing, Database] = + ZLayer.fromFunction { env: ConnectionSource with Blocking with Clock => new DatabaseServiceBase[Connection](env.get[ConnectionSource.Service]) with Database.Service { override final def connectionFromJdbc(connection: JdbcConnection): ZIO[Any, Nothing, Connection] = self.connectionFromJdbc(env, connection) diff --git a/src/main/scala/io/github/gaelrenoux/tranzactio/test/DatabaseModuleTestOps.scala b/src/main/scala/io/github/gaelrenoux/tranzactio/test/DatabaseModuleTestOps.scala index 7e0dd61..77446d3 100644 --- a/src/main/scala/io/github/gaelrenoux/tranzactio/test/DatabaseModuleTestOps.scala +++ b/src/main/scala/io/github/gaelrenoux/tranzactio/test/DatabaseModuleTestOps.scala @@ -3,6 +3,7 @@ package io.github.gaelrenoux.tranzactio.test import io.github.gaelrenoux.tranzactio.{DatabaseModuleBase, DatabaseOps, DbException, ErrorStrategiesRef} import izumi.reflect.Tag import zio.blocking.Blocking +import zio.clock.Clock import zio.{Has, ZIO, ZLayer} /** Testing utilities on the Database module. */ @@ -12,11 +13,11 @@ trait DatabaseModuleTestOps[Connection <: Has[_]] extends DatabaseModuleBase[Con /** A Connection which is incapable of running anything, to use when unit testing (and the queries are actually stubbed, * so they do not need a Database). Trying to run actual queries against it will fail. */ - def noConnection(env: Blocking): ZIO[Any, Nothing, Connection] = connectionFromJdbc(env, NoopJdbcConnection) + def noConnection(env: Blocking with Clock): ZIO[Any, Nothing, Connection] = connectionFromJdbc(env, NoopJdbcConnection) /** A Database which is incapable of running anything, to use when unit testing (and the queries are actually stubbed, * so they do not need a Database). Trying to run actual queries against it will fail. */ - lazy val none: ZLayer[Blocking, Nothing, Database] = ZLayer.fromFunction { b: Blocking => + lazy val none: ZLayer[Blocking with Clock, Nothing, Database] = ZLayer.fromFunction { b: Blocking with Clock => new Service { override def transactionR[R <: Has[_], E, A](zio: ZIO[Connection with R, E, A], commitOnFailure: Boolean) (implicit errorStrategies: ErrorStrategiesRef): ZIO[R, Either[DbException, E], A] = diff --git a/src/test/scala/io/github/gaelrenoux/tranzactio/integration/AnormIT.scala b/src/test/scala/io/github/gaelrenoux/tranzactio/integration/AnormIT.scala index 12b1d61..0eaa04c 100644 --- a/src/test/scala/io/github/gaelrenoux/tranzactio/integration/AnormIT.scala +++ b/src/test/scala/io/github/gaelrenoux/tranzactio/integration/AnormIT.scala @@ -6,6 +6,7 @@ import io.github.gaelrenoux.tranzactio.anorm._ import samples.Person import samples.anorm.PersonQueries import zio.blocking.Blocking +import zio.clock.Clock import zio.test.Assertion._ import zio.test._ import zio.{ULayer, ZLayer} @@ -13,7 +14,7 @@ import zio.{ULayer, ZLayer} /** Integration tests for Doobie */ object AnormIT extends ITSpec[Database, PersonQueries] { - override val dbLayer: ZLayer[ConnectionSource with Blocking, Nothing, Database] = Database.fromConnectionSource + override val dbLayer: ZLayer[ConnectionSource with Blocking with Clock, Nothing, Database] = Database.fromConnectionSource override val personQueriesLive: ULayer[PersonQueries] = PersonQueries.live diff --git a/src/test/scala/io/github/gaelrenoux/tranzactio/integration/DoobieIT.scala b/src/test/scala/io/github/gaelrenoux/tranzactio/integration/DoobieIT.scala index cb38423..c7ce05a 100644 --- a/src/test/scala/io/github/gaelrenoux/tranzactio/integration/DoobieIT.scala +++ b/src/test/scala/io/github/gaelrenoux/tranzactio/integration/DoobieIT.scala @@ -7,6 +7,7 @@ import io.github.gaelrenoux.tranzactio.doobie._ import samples.Person import samples.doobie.PersonQueries import zio.blocking.Blocking +import zio.clock.Clock import zio.test.Assertion._ import zio.test._ import zio.{ULayer, ZLayer} @@ -15,7 +16,7 @@ import zio.{ULayer, ZLayer} /** Integration tests for Doobie */ object DoobieIT extends ITSpec[Database, PersonQueries] { - override val dbLayer: ZLayer[ConnectionSource with Blocking, Nothing, Database] = Database.fromConnectionSource + override val dbLayer: ZLayer[ConnectionSource with Blocking with Clock, Nothing, Database] = Database.fromConnectionSource override val personQueriesLive: ULayer[PersonQueries] = PersonQueries.live