4

我正在尝试将项目从猫效果 2 迁移到猫效果 3,我正在使用 doobie 与数据库进行交互。以前我可以ConnectionIOIO描述那样提升,但是随着升级我没有找到任何实现LiftIO[ConnectionIO],如何用 CE3 实现相同的目标?

4

2 回答 2

3

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

“不要那样做”

一般来说,不建议将任意代码交错IOConnectionIO程序中,因为ConnectionIO它是事务性的,您无法回滚IO. AConnectionIO可能会运行多次,例如重试可恢复的故障。

如果可能,最好重构代码以不在事务内执行非事务性操作,而是在事后执行

但是,当这不切实际时,ConnectionIO提供一个Sync实例,因此您可以轻松地使用它做很多事情,而无需从IO一开始就进行提升:

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

使用WeakAsync

Doobie'sWeakAsync提供了一种获取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)
}
于 2022-02-24T20:03:26.250 回答
0

我找到了实现它的方法

def f()(implicit liftToConnectionIO: FunctionK[IO, ConnectionIO]): IO[Unit] = IO.unit
implicit val liftToConnectionIO = WeakAsync.liftK[IO, ConnectionIO]
liftToConnectionIO.use(implicit lift => f())
于 2022-02-21T20:03:58.930 回答