在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
答案 0 :(得分:5)
假设您有一个演员A
向演员B
发送消息而A
期望来自B
的某种响应消息。在B
内部,为了让它完成工作,出于某种原因需要Future
。在Future
完成后,它希望将结果发送回A
。编码B
的人在回复sender()
时要小心不要关闭A
,因此他们使用pipeTo
模式,如下所示:
fut pipeTo sender()
现在回到A
,你期待某种类型的回应,你不应该处理演员B
的内部错综复杂以及它需要{{1}的事实为了做它的工作。换句话说,您不希望回复包含在Future
(scala.util.Try
或Success
)中。如果您期望Failure
,那么如果一切顺利,那就是您想要从String
返回的内容。但是在B
中一切都不顺利的情况下,B
需要知道这一点,而Akka团队选择这样做的方式是将其包裹在A
中。这对我来说似乎比原样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
回到sender()
,我们就会这样做:
Future
这样我们就不必在任何地方真正处理fut.recover{case ex => Failure(someErrorMessage, Some(ex)} pipeTo sender()
。
答案 1 :(得分:1)
future onComplete
将解析为scala.util.Success(futureResult)
或scala.util.Failure(someThrowable)
。
如果未来成功,可以直接取回futureResult
。
如果未来失败,你可能不想收到一个未包装的扔掉的东西。将其重新包裹在akka.actor.status.Failure
中会更好。