I am trying to migrate project from cats-effect 2 to cats-effect 3, i am using doobie for interacting with database. Previously i could lift ConnectionIO
to IO
as it was described, but with the upgrade i didn't find any implementation of LiftIO[ConnectionIO]
, how can be same achieved with CE3?

- 93
- 5
2 Answers
There's two approaches here. Broadly, there's the "don't do that" option (recommended), and the other way would be to use WeakAsync
"Don't do that"
Generally, it's not recommended to interleave arbitrary IO
into a ConnectionIO
program, because ConnectionIO
is transactional, and you cannot roll back an IO
. A ConnectionIO
might run multiple times, for example to retry a recoverable failure.
When possible, it's a good idea to refactor the code to not do the non-transactional operation inside a transaction, but instead to perform it afterwards
However, when that's not practical, ConnectionIO
provides a Sync
instance, and so there's a number of things you can do with it easily that don't require lifting from IO
in the first place:
- printing to the console can be done by summoning
Console[ConnectionIO]
- Getting the current time can be done with
Clock[ConnectionIO]
- You can create a log4cats
Logger[ConnectionIO]
as needed using the appropriate factory for your backend - Generating a UUID value can be done with
UUIDGen[ConnectionIO]
Using WeakAsync
Doobie's WeakAsync
provides a way to get a Resource[F, F ~> ConnectionIO]
Note that because this is a resource, you must take care to complete the transaction inside of use
- the lifecycle of the FunctionK
from the resource will be shut down once use
completes.
Usually that means something like this:
def doStuff(rows: List[Int]): F[Unit] = ???
WeakAsync.liftK[F, ConnectionIO].use { fk =>
val transaction = for {
rows <- sql"select 1".query[Int].to[List]
_ <- fk(doStuff(rows))
} yield ()
transaction.transact(xa)
}

- 35,856
- 13
- 85
- 124
I found the way to achieve it by
def f()(implicit liftToConnectionIO: FunctionK[IO, ConnectionIO]): IO[Unit] = IO.unit
implicit val liftToConnectionIO = WeakAsync.liftK[IO, ConnectionIO]
liftToConnectionIO.use(implicit lift => f())

- 93
- 5
-
As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 22 '22 at 07:05