捕获杀死演员的消息

时间:2015-10-14 21:02:17

标签: scala akka actor

当接收演员因该消息而死亡时,我正在尝试回复消息的发送者。如果我Restart失败的演员我得到了

preRestart(reason: Throwable, message: Option[Any])

但现在我决定重新启动。

如果我是Stop演员,我只能

postStop()

不知道是什么阻止了我自己。

与此同时,在主管中,我只得到Throwable并且没有任何迹象表明它是什么原因。

我想,我可以通过DeadLetters帖子演员终止,但这似乎是一个嘈杂的方法,因为我必须听所有死信,并在某处将终止与deadletter事件流相关联

更新: DeadLetter似乎不是一个选项。导致死亡的消息甚至没有发送到DeadLetters,它只是消失了。

我有一种机制可以忽略吗?

1 个答案:

答案 0 :(得分:1)

根据Akka用户名单上的this thread,行动者监督死亡周期中没有一种机制可以实现这一目标。此外,文档明确声明消息已被删除:

  

What happens to the Message

     

如果在处理邮件时抛出异常(即从邮箱中取出并移交给当前行为),则此邮件将丢失。重要的是要了解它没有放回邮箱。因此,如果要重试处理消息,则需要通过捕获异常并重试流程来自行处理。

理想的解决方案是使用专用的参与者进行危险的操作,并让发起者监视该参与者的死亡以确定失败。

由于我的场景来自于被认为是 safe 的内容,但其中有一个错误,因此单独的actor选项在之后就是。为了避免在try/catch中包装所有代码路径但能够保护更复杂和关键的流,我最终创建了一个receive的包装器,让我拦截异常:

object SafeReceive {
  def apply(receive: Receive)(recover: Any => PartialFunction[Throwable, Unit]): Receive =
    new Receive {
      override def isDefinedAt(x: Any): Boolean = receive.isDefinedAt(x)

      override def apply(v1: Any): Unit = try {
        receive(v1)
      } catch recover(v1)
    }
}

我可以用于这样的精选演员:

def receive = SafeReceive {
  case ... => ...
} {
  msg => {
    case e: Exception =>
      sender ! OperationFailed(msg, e)
      throw e
  }
}