重试Monix任务-为什么在这里需要Task.defer?

时间:2018-10-27 19:24:42

标签: scala functional-programming monads monix doobie

我最近发现一个与Monix Task合作时无法完全理解的案例:

有两个函数(在队列消息处理程序中):

  def handle(msg: RollbackMsg): Task[Unit] = {
    logger.info(s"Attempting to rollback transaction ${msg.lockId}")
    Task.defer(doRollback(msg)).onErrorRestart(5).foreachL { _ =>
      logger.info(s"Transaction ${msg.lockId} rolled back")
    }
  }

  private def doRollback(msg: RollbackMsg): Task[Unit] =
    (for {
      originalLock         <- findOrigLock(msg.lockId)
      existingClearanceOpt <- findExistingClearance(originalLock)
      _                    <- clearLock(originalLock, existingClearanceOpt)
    } yield ()).transact(xa)

doRollback的理解力内部是一组doobie个调用,它们返回ConnectionIO[_] monad,然后在其上运行transact,将构图变成Monix Task

现在,如handle函数所示,我希望整个过程在失败的情况下重试5次。神秘的部分是这个简单的调用:

doRollback(msg).onErrorRestart(5)

并不会真正在异常上重新启动操作(已在测试中验证)。为了获得这种重试行为,我必须将其显式包装在Task.defer中,或者以任何其他方式将其包含在Task“上下文”中。

这是我没有完全明白的要点:为什么会这样? doRollback已经给了我Task实例,所以我应该可以在它上调用onErrorRestart,不是吗?如果不是这种情况,如何确定从“某处”获得的Task实例是否可以重新启动?

我在这里想念什么?

0 个答案:

没有答案