Skip to content

Expose ConnectionIO API for Doobie module #110

@salamonpavel

Description

@salamonpavel

Background

At the moment the DoobieEngine executes queries within a single complete transaction. Nevertheless Doobie offers also ConnectionIO API which allows to process several queries as one transaction within a for-comprehension block. In other words ConnectionIO allows for functional composition given it's a Monad.

val xa = Transactor.fromDriverManager[IO](
  driver = "org.postgresql.Driver", 
  url = "jdbc:postgresql:world", 
  user = "postgres",    
  password = "password"    
)

val program: ConnectionIO[(Int, Double)] =
  for {
    a <- sql"select 42".query[Int].unique // here imagine our db function invocation with connectionIO
    b <- sql"select random()".query[Double].unique // here imagine our db function invocation with connectionIO
  } yield (a, b)

program.transact(xa).unsafeRunSync()

As mentioned above the DoobieEngine currently defines the operation in terms of higher-kinded effect type F[_].

private def executeQuery[R](query: QueryType[R])(implicit readR: Read[R]): F[Seq[R]] = {
    query.fragment.query[R].to[Seq].transact(transactor)
  }

We could expose also the ConnectionIO. ConnectionIO is not tied to cats.effect.IO or any other specific effect type. ConnectionIO[A] is simply a type alias for Free[ConnectionOp, A], where ConnectionOp is a type that represents a low-level JDBC operation and Free is a type from the Cats library that represents a computation in the free monad of a functor.

private def executeQueryConnectionIO[R](query: QueryType[R])(implicit readR: Read[R]): ConnectionIO[Seq[R]] = {
    query.fragment.query[R].to[Seq]
  }

Having access to ConnectionIO API we could implement better integration tests as we could execute multiple database calls withing a single transaction.

Moreover Transactor's Strategy can be configured as needed for the purposes of testing, for instance setting auto-rollback.

val testXa = Transactor.after.set(xa, HC.rollback)

Compositionality of ConnectionIO together with Transactor with rollback effectively enables easy integration testing of our database functions. No additional testing library would be needed. Test assertions could be performed within a for-comprehension block (transaction boundary) and automatically rolled back.

Unfortunately Slick and Doobie have very different APIs and this posses a design challenge. Ideally we would like to keep Slick and Doobie APIs exposed by fa-db the same for features supported by both libraries and at the same time expose functionality Doobie offers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    🆕 To groom

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions