如何在akka演员接收的模式匹配中提前返回

时间:2017-10-16 10:47:04

标签: scala syntax akka partialfunction

尝试使用谷歌搜索这个微不足道的问题,但没有得到答案......

基本上我的receive方法中有一个模式匹配。 在某些情况下,我想提前从接收处理中解脱

    override def receive = {
        case blah => {
          ... preflight code
          if (preflight failed) {
            sender() ! errorMSG 
            "break" or "return" here // get error "method receive has a return statement ; needs result type - 
// I tried adding Unit to the receive and return statements
          }
          ... more code
           ....

          if (something happened) {
            sender() ! anotherErrorMSG
            "break" or "return" here
          }
          ...
       }
       case foo => {...}
       case bar => {...}
     } // end receive

2 个答案:

答案 0 :(得分:1)

请参阅this discussion of return's semantics并记住接收返回PartialFunction [Any,Unit],然后在返回receive之后对其进行评估。简而言之,没有办法尽早返回。

ÖmerErden的抛出异常并使用actor监督工作的解决方案(实际上,抛出所有开销的异常基本上是提前可靠地结束计算的唯一方法),但是如果你需要任何状态来从消息转移到消息,你需要Akka持久性。

如果你不想像在chunjef的解决方案中那样嵌套if-elses,你可以使用context.become和stash来创建一些spaghetti-ish代码。

但最好的解决方案可能是使用任何结果类型让可能失败的东西成为他们自己的函数。请注意,scala 2.12中的Either API比以前的版本更好。

import scala.util.{ Either, Left, Right }

type ErrorMsg = ...
type PreflightSuccess = ... // contains anything created in preflight that you need later
type MoreCodeSuccess = ... // contains anything created in preflight or morecode that you need later

def preflight(...): Either[ErrorMsg, PreFlightSuccess] = {
  ... // preflight
  if (preflight failed)
    Left(errorMsg)
  else
    Right(...) // create a PreflightSuccess
}

def moreCode1(pfs: PreFlightSuccess): Either[ErrorMsg, MoreCodeSuccess] = {
  ... // more code
  if (something happened)
    Left(anotherErrorMSG)
  else
    Right(...) // create a MoreCodeSuccess
}

def moreCode2(mcs: MoreCodeSuccess): Either[ErrorMsg, Any] = {
  ... // more code, presumably never fails
  Right(...)
}

override def receive = {
  case blah =>
    val pf = preflight(...)
    val result = pf.map(morecode1).joinRight.map(moreCode2).joinRight // only calls morecode1 if preflight succeeded, and only calls morecode2 if preflight and morecode1 succeeded
    result.fold(
      { errorMsg => sender ! errorMsg },
      ()
    )
  case foo => ...
  case bar => ...
}

这是否优于嵌套if-else是一个品味问题......

答案 1 :(得分:0)

这可能不是您的问题的确切答案,但在您的情况下,添加supervisor演员将是更好的解决方案。在Akka监督模型中,说服您处理主管演员的异常,而不是将错误消息发送回发件人。

这种方法为您带来容错模型,并且您可以在您想要的任何行上抛出异常(这解决了您当前的问题),您的主管演员将通过重新启动,恢复或处理抛出阻止儿童演员。

请查看link