Skip to content

Commit

Permalink
Updates README and improves samples
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelrenoux committed Mar 24, 2024
1 parent d472673 commit 351a62b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 14 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,36 @@ val es: ErrorStrategies =



### Multiple Databases

Some applications use multiple databases.
In that case, it is necessary to have them be different types in the ZIO environment.

Tranzactio offers a typed database class, called `DatabaseT[_]`.
You only need to provide a different marker type for each database you use.

```scala
import io.github.gaelrenoux.tranzactio.doobie._
import javax.sql.DataSource
import zio._

trait Db1
trait Db2

val db1Layer: ZLayer[Any, Nothing, DatabaseT[Db1]] = datasource1Layer >>> Database[Db1].fromDatasource
val db2Layer: ZLayer[Any, Nothing, DatabaseT[Db2]] = datasource2Layer >>> Database[Db2].fromDatasource

val queries1: ZIO[Connection, DbException, List[String]] = ???
val zio1: ZIO[DatabaseT[Db1], DbException, List[Person]] = DatabaseT[Db1].transactionOrWiden(queries1)
val zio2: ZIO[DatabaseT[Db2], DbException, List[Person]] = DatabaseT[Db2].transactionOrWiden(queries1)
```

When creating the layers for the datasources, don't forget to use `.fresh` when you have sub-layers of the same type on both sides!

You can see a full example in the `examples` submodule (in `LayeredAppMultipleDatabases`).



### Single-connection Database

In some cases, you might want to have a `Database` module representing a single connection.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package samples.anorm

import io.github.gaelrenoux.tranzactio.DbException
import io.github.gaelrenoux.tranzactio.{DbException, ErrorStrategies}
import io.github.gaelrenoux.tranzactio.anorm._
import samples.{Conf, ConnectionPool, Person}
import zio._

import javax.sql.DataSource

/** A sample app where all modules are linked through ZLayer. Should run as is (make sure you have com.h2database:h2 in
* your dependencies). */
object LayeredAppMultipleDatabases extends zio.ZIOAppDefault {
Expand All @@ -15,19 +17,19 @@ object LayeredAppMultipleDatabases extends zio.ZIOAppDefault {
/** Marker trait for the second DB */
trait Db2

private val database1: ZLayer[Any, Any, DatabaseT[Db1]] = {
private val database1: ZLayer[Any, Throwable, DatabaseT[Db1]] = {
// Fresh calls are required so that the confs and datasource aren't conflated with the other layer's
val conf = Conf.live("samble-anorm-app-1").fresh
val dbRecoveryConf = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource = conf >>> ConnectionPool.live.fresh
val dbRecoveryConf: ZLayer[Any, Nothing, ErrorStrategies] = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource: ZLayer[Any, Throwable, DataSource] = conf >>> ConnectionPool.live.fresh
(datasource ++ dbRecoveryConf) >>> DatabaseT[Db1].fromDatasourceAndErrorStrategies
}

private val database2: ZLayer[Any, Any, DatabaseT[Db2]] = {
private val database2: ZLayer[Any, Throwable, DatabaseT[Db2]] = {
// Fresh calls are required so that the confs and datasource aren't conflated with the other layer's
val conf = Conf.live("samble-anorm-app-2").fresh
val dbRecoveryConf = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource = conf >>> ConnectionPool.live.fresh
val dbRecoveryConf: ZLayer[Any, Nothing, ErrorStrategies] = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource: ZLayer[Any, Throwable, DataSource] = conf >>> ConnectionPool.live.fresh
(datasource ++ dbRecoveryConf) >>> DatabaseT[Db2].fromDatasourceAndErrorStrategies
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package samples.doobie

import io.github.gaelrenoux.tranzactio.DbException
import io.github.gaelrenoux.tranzactio.{DbException, ErrorStrategies}
import io.github.gaelrenoux.tranzactio.doobie._
import samples.{Conf, ConnectionPool, Person}
import zio._

import javax.sql.DataSource

/** A sample app with two databases for different set of queries. */
object LayeredAppMultipleDatabases extends zio.ZIOAppDefault {

Expand All @@ -14,19 +16,19 @@ object LayeredAppMultipleDatabases extends zio.ZIOAppDefault {
/** Marker trait for the second DB */
trait Db2

private val database1: ZLayer[Any, Any, DatabaseT[Db1]] = {
private val database1: ZLayer[Any, Throwable, DatabaseT[Db1]] = {
// Fresh calls are required so that the confs and datasource aren't conflated with the other layer's
val conf = Conf.live("samble-doobie-app-1").fresh
val dbRecoveryConf = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource = conf >>> ConnectionPool.live.fresh
val dbRecoveryConf: ZLayer[Any, Nothing, ErrorStrategies] = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource: ZLayer[Any, Throwable, DataSource] = conf >>> ConnectionPool.live.fresh
(datasource ++ dbRecoveryConf) >>> DatabaseT[Db1].fromDatasourceAndErrorStrategies
}

private val database2: ZLayer[Any, Any, DatabaseT[Db2]] = {
private val database2: ZLayer[Any, Throwable, DatabaseT[Db2]] = {
// Fresh calls are required so that the confs and datasource aren't conflated with the other layer's
val conf = Conf.live("samble-doobie-app-2").fresh
val dbRecoveryConf = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource = conf >>> ConnectionPool.live.fresh
val dbRecoveryConf: ZLayer[Any, Nothing, ErrorStrategies] = conf >>> ZLayer.fromFunction((_: Conf).dbRecovery).fresh
val datasource: ZLayer[Any, Throwable, DataSource] = conf >>> ConnectionPool.live.fresh
(datasource ++ dbRecoveryConf) >>> DatabaseT[Db2].fromDatasourceAndErrorStrategies
}

Expand Down

0 comments on commit 351a62b

Please sign in to comment.