This repository has been archived and is now read-only.
This project will no longer be maintained and new versions will no longer be published.
- The code and all issues, pull requests, and discussions are still accessible in a read-only state.
- No further updates, bug fixes, or support will be provided.
Thank you for your contributions and support!
DBZIO is a wrapper to combine ZIO and DBIO actions in one for-comprehension. Unlike other libraries, DBZIO provides possibility to run the resulting action in a context of database transaction.
Add dependency to the project
libraryDependencies += "com.riskident" %% "dbzio" % <Version>
In the code:
import com.riskident.dbzio._
import slick.jdbc.<SomeProfile>.api._
import zio._
...
// Read data from DB
val readFromDb: DBIO[Vector[Data]] = sql"SELECT * FROM table".as[Data]
// Get relevant data from a remote service
val transformData: Vector[Data] => Task[List[OtherData]] = ...
// Save updated data in DB
val saveDataInDb: List[OtherData] => DBIO[Int] = data => sqlu"INSERT INTO table2 VALUES ($data)"
// The combined action
val action = for {
data <- DBZIO(readFromDb)
newData <- DBZIO(transformData(data))
res <- DBZIO(saveDataInDb(newData))
} yield res
// The overall action should run within a db-transaction
val dbzioAction: DBZIO[Any, Int] = action.transactionally
// Back to ZIO world
val zioAction: RIO[DbDependency, Int] = dbzioAction.result
In the example above:
- some data is read from DB
- this data is sent to some remote service, which returns a new data relevant to the one being sent
- received data is saved in the DB
The whole operation is done inside db-transaction
DBZIO provides a way to easily provide DbDependency
for tests. In order to achieve it, add a dependency to the project
libraryDependencies += "com.riskident" %% "dbzio-test" % <Version> % Test
And in tests add the following:
import com.riskident.dbzio.{Db, DbDependency, TestLayers}
import com.typesafe.config.ConfigFactory
import slick.jdbc.H2Profile.api.{Database => _}
import slick.jdbc.JdbcBackend.Database
import zio.test._
import zio.{Task, ZIO, ZLayer}
object Example1 extends ZIOSpecDefault with TestLayers {
override type Config = com.typesafe.config.Config
override def produceConfig(string: String): Task[Config] = ZIO.attempt {
ConfigFactory
.parseString(string)
.resolve()
}
override def makeDb(config: Config): Task[Database] =
ZIO.attempt(Db.forConfig(path = "db", config = config, classLoader = this.getClass.getClassLoader))
val testLayer: ZLayer[TestEnvironment, TestFailure[Throwable], DbDependency] = testDbLayer.mapError(TestFailure.fail)
override def spec: Spec[TestEnvironment, Any] =
suite("Some tests using db")(...).provideLayer(testLayer)
}
This will allow to use H2 in-memory database with random name in each test, effectively running tests in parallel with separate databases.