Doobie - 将任意效果提升到 ConnectionIO CE3

Doobie - lifting arbitrary effect into ConnectionIO CE3

我正在尝试将项目从 cats-effect 2 迁移到 cats-effect 3,我正在使用 doobie 与数据库进行交互。以前我可以将 ConnectionIO 提升到 IO,因为它是 ,但是随着升级我没有找到 LiftIO[ConnectionIO] 的任何实现,CE3 如何实现相同的?

我找到了实现方法

def f()(implicit liftToConnectionIO: FunctionK[IO, ConnectionIO]): IO[Unit] = IO.unit
implicit val liftToConnectionIO = WeakAsync.liftK[IO, ConnectionIO]
liftToConnectionIO.use(implicit lift => f())

这里有两种方法。一般来说,有“不要那样做”选项(推荐),另一种方法是使用 WeakAsync

“不要那样做”

通常,不建议将任意 IO 插入到 ConnectionIO 程序中,因为 ConnectionIO 是事务性的,您无法回滚 IOConnectionIO 可能 运行 多次,例如重试可恢复的故障。

如果可能,重构代码以不在事务内执行 non-transactional 操作,而是在事后执行它是个好主意

然而,当这不可行时,ConnectionIO 提供了一个 Sync 实例,因此您可以使用它轻松完成许多不需要从 [=12= 提升的事情] 第一名:

  • 可以通过召唤 Console[ConnectionIO]
  • 打印到控制台
  • 获取当前时间可以用Clock[ConnectionIO]
  • 完成
  • 您可以根据需要使用适合您后端的工厂创建 log4cats Logger[ConnectionIO]
  • 可以使用 UUIDGen[ConnectionIO]
  • 生成 UUID 值

使用WeakAsync

Doobie 的 WeakAsync 提供了一种获取 Resource[F, F ~> ConnectionIO]

的方法

请注意,因为这是一个资源,所以您必须注意在 use 内部完成事务 - 来自该资源的 FunctionK 的生命周期将关闭一次 use 完成。

通常意思是这样的:

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)
}