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



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

基本上我的接收方法中有一个模式匹配。在某些情况下,我想尽早从接收处理中中断

    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

请参阅对返回语义的讨论,并记住 receive 返回一个 PartialFunction[Any, Unit],然后在 receive 返回后对其进行计算。 简而言之,没有办法提前返回。

Ömer Erden 抛出异常并使用 actor 监督的解决方案有效(事实上,抛出异常及其所有开销基本上是可靠地提前结束计算的唯一方法),但如果你需要任何状态从一个消息传递到另一个消息,你需要 Akka 持久性。

如果你不想像 chunjef 的解决方案那样嵌套 if-elses,你可以使用 context.become 和 stash 来创建一些意大利面条式的代码。

但最好的解决方案可能是让可能失败的东西是它们自己的函数,具有任一结果类型。 请注意,scala 2.12 中的任一 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 更可取是一个品味问题......

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

这种方法为你带来了一个容错模型,你也可以在任何你想要的行抛出异常(这解决了你当前的问题),你的主管Actor将通过重新启动、恢复或停止子Actor来处理抛出的。

请检查链接

相关内容

  • 没有找到相关文章