【问题标题】:Future pipeTo failure is wrapped inside akka.actor.status.Failure?未来的 pipeTo 失败被包裹在 akka.actor.status.Failure 中?
【发布时间】:2015-07-29 13:19:54
【问题描述】:

当在 Akka 中使用管道模式时,未来失败的结果被包装在 akka.actor.status.Failure 中,但是未来的成功结果不会被包装在相应的 akka.actor.status.Success 中。

我想知道这个决定背后的原因是什么?为什么只有失败而不是成功?

根本不包装任何东西似乎更合乎逻辑。

这里是实现的链接: https://github.com/akka/akka/blob/v2.4-M2/akka-actor/src/main/scala/akka/pattern/PipeToSupport.scala

【问题讨论】:

    标签: akka


    【解决方案1】:

    假设您有一个演员A 向演员B 发送消息,而A 期望来自B 的某种响应消息。在B 内部,为了使其工作,出于某种原因,它需要Future。在Future 完成之后,它想将结果发送回A。编码B 的人在回复A 时要小心不要关闭sender(),因此他们使用pipeTo 模式,如下所示:

    fut pipeTo sender()
    

    现在回到A,您期待某种类型的响应,并且您不必处理演员B 的内部复杂性以及它需要Future 才能做到这一点的事实这是工作。换句话说,您不希望回复以scala.util.TrySuccessFailure)的形式返回给您。如果您期待String,那么如果一切顺利,这正是您希望从B 得到的结果。但是在B 中一切都不顺利的情况下,A 需要知道这一点,而 Akka 团队选择这样做的方式是将其包裹在 Status.Failure 中。这对我来说似乎比发送原始的Exception 要好。

    现在,我们在参与者之间使用标准的通信模型,其中我们有类似于这个简单模型的东西(为简洁起见):

    sealed trait ServiceResult[+A]
    case object EmptyResult extends ServiceResult[Nothing]
    case class FullResult[+A](value:A) extends ServiceResult[A]
    case class Failure(error:ErrorMessage, ex:Option[Throwable]) extends ServiceResult[Nothing]
    

    所有服务总是以某种形式的ServiceResult 进行响应。因此,如果我们从 Future 管道返回到 sender(),我们会这样做:

    fut.recover{case ex => Failure(someErrorMessage, Some(ex)} pipeTo sender()
    

    这样我们就不必在任何地方真正处理Status.Failure

    【讨论】:

    • 这很好地解释了我的直觉,Status.Failure 是不必要的。如果您想与演员A 沟通他请求的操作失败,您将以特定于域的方式对其进行编码。换句话说,您需要将Status.Failure 转换为某个域对象。您跳过了失败的处理,因为您的未来永远不会真正失败,因此始终会调用 PipeableFuture 中的成功案例。
    • 正如你在上一个声明中所说,你避免了处理Status.Failure,这在某种程度上暗示它不应该存在。
    • Akka 内部需要它。当您使用ask 时,将使用一个短暂的参与者来代理请求/响应语义。我想Status.Failure 被用来告诉那个短命的演员让上游Future 失败,它代表失败发生的时间。我认为这就是它存在的原因。碰巧的是,当您使用pipe 时它会溢出,最终您会遇到它。此外,如果您知道您正在通过询问被调用。使用Status.Failure 响应是一种快速让上游Future 失败的方法,而无需在 Future 上使用flatMap 来检查结果并且可能会失败
    • 向参与者发送消息很像创建Future - 这些都是异步操作。如果 Scala 开发人员选择使用成功-失败的格式进行异步构造,为什么 Akka 会有所不同?那只会造成混乱。此外,您说您基本上创建了自己的自定义scala.util.Try,这(可能)表明了开发人员围绕该主题的共同直觉。我本来希望pipeToTry 的形式返回,也许可以选择使用pipeTo actorX as MyCustomTry 指定自定义返回类型(类似于Try)。
    【解决方案2】:

    future onComplete 将解析为 scala.util.Success(futureResult)scala.util.Failure(someThrowable)

    如果future成功了,直接取回futureResult就方便了。

    如果未来失败,您可能不想收到未包装的可投掷物。用akka.actor.status.Failure 包裹起来会更好。

    【讨论】:

    • 但是 scala.util.Failure 不是已经达到了这个目的吗?以及处理 Actor 中的 scala.util.{Success, Failure} 有什么问题?
    • 但是你没有得到 akka.actor.status.Failure(scala.util.Failure(throwable)),你得到的只是 akka.actor.status.Failure(throwable)。它不是双重包装的。而且我认为恢复演员状态失败比恢复未来失败更有意义。
    • 我应该更明确一点。为什么实现将失败包装在 akka.actor.status.Failure 中而不是 scala.util.Failure 中?演员状态失败就是失败。我认为没有必要在这里重新发明轮子(失败)。
    • actor.status.Failure 上的文档是:“此类/消息类型最好用于指示执行的某些操作失败。例如,它用于指示使用 AskSupport 的失败(问/?)。”当处理期货时,你会得到一个未来的失败,当你对一个演员执行操作时,你会得到一个演员状态失败。对我来说很有意义。
    猜你喜欢
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多