如何 return 在 akka actor 的模式匹配中尽早接收
How to return early in a pattern match of akka actor 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
这可能不是您问题的确切答案,但在您的情况下添加 supervisor actor 将是更好的解决方案。在 Akka 监督模型中,说服您处理监督者 actor 上的异常,而不是将错误消息发送回发送者。
这种方法给你带来了一个容错模型,而且你可以在任何你想要的行抛出异常(这解决了你当前的问题),你的主管actor会处理throwable重新启动,恢复或停止子演员。
请检查link
参见 this discussion of return's semantics 并记住 receive return 是一个 PartialFunction[Any, Unit],然后在 receive returned 之后对其求值。总之没办法return早
Ömer Erden 抛出异常并使用 actor 监督的解决方案有效(事实上,抛出所有开销的异常基本上是尽早可靠地结束计算的唯一方法),但是如果您需要任何状态从消息到消息,你需要 Akka 持久性。
如果您不想像 chunjef 的解决方案那样嵌套 if-elses,您可以使用 context.become 和 stash 来创建一些意大利面条式的代码。
但最好的解决方案可能是让可能失败的事情成为它们自己的函数,结果类型为 Either。请注意,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 更可取是一个品味问题...
尝试用谷歌搜索这个微不足道的问题,但没有得到答案...
基本上我的接收方法中有一个模式匹配。 在某些情况下,我想提前中断接收处理
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
这可能不是您问题的确切答案,但在您的情况下添加 supervisor actor 将是更好的解决方案。在 Akka 监督模型中,说服您处理监督者 actor 上的异常,而不是将错误消息发送回发送者。
这种方法给你带来了一个容错模型,而且你可以在任何你想要的行抛出异常(这解决了你当前的问题),你的主管actor会处理throwable重新启动,恢复或停止子演员。
请检查link
参见 this discussion of return's semantics 并记住 receive return 是一个 PartialFunction[Any, Unit],然后在 receive returned 之后对其求值。总之没办法return早
Ömer Erden 抛出异常并使用 actor 监督的解决方案有效(事实上,抛出所有开销的异常基本上是尽早可靠地结束计算的唯一方法),但是如果您需要任何状态从消息到消息,你需要 Akka 持久性。
如果您不想像 chunjef 的解决方案那样嵌套 if-elses,您可以使用 context.become 和 stash 来创建一些意大利面条式的代码。
但最好的解决方案可能是让可能失败的事情成为它们自己的函数,结果类型为 Either。请注意,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 更可取是一个品味问题...