[英]Akka: how can I catch failure of one actor inside another (non child) actor?
我有兩個演員:
處理系統中某些進程的ProcessManager (例如,用戶注冊,購買等)
通知程序 - 如果ProcessManager中發生了某些錯誤,則應通知用戶。 我需要捕獲ProcessManager actor的失敗(它失敗並因任何原因而停止,例如,因為ActorInitializationException或達到最大重啟時間並且進程管理器actor被停止)。
class ProcessManager extends Actor {
override def receive: Receive = {
...
}
}
class Notifier extends Actor {
override def receive: Receive = {
PROCESS MANAGER ACTOR FAILED AND STOPPED =>
// Here I need to catch failure of ProcessManager actor
// (it was failed and stopped for what ever
// reason, for example, because of ActorInitializationException
// or max restart time reached and Process manager actor was stopped).
//
// Then do some stuff, for example, send message to the client via web socket.
}
}
class MyController @Inject() (cc: ControllerComponents, actorSystem: ActorSystem)
(implicit exec: ExecutionContext) extends AbstractController(cc) {
// I need to catch failure of processManager in this actor.
val notifier = actorSystem.actorOf(Props(classOf[Notifier]))
def registerUser = Action.async {
// Actor may be stopped because of ActorInitializationException here
val processManager = actorSystem.actorOf(Props(classOf[ProcessManager]))
...
// OR it may be stopped here for any reason.
processManager ! "some message which will fail and stop pm actor"
Future.successfull(Ok("Thanks."))
}
}
如何在Notifier actor中捕獲ProcessManager actor的終止(因為失敗)?
編輯讓我解釋一下我的問題的背景。
我正在Play控制器中創建PM演員並將消息發送給它(Tell),我立即向用戶返回Ok響應。 PM actor創建另一個子actor,在創建過程中拋出ActorInitializationException。 我需要通知用戶(通過Web套接字,使用Notifier actor),出現問題。
當ProcessManager
actor永久停止時,您可以使用DeathWatch
注冊Notifier
actor以接收Terminated
消息。 Notifier
將需要對DeathWatch
的ProcessManager
actor的DeathWatch
,並且一種方法是將對ProcessManager
的引用作為消息發送(這是安全的,因為ActorRef
是不可變的和可序列化的)。
class Notifier extends Actor {
var processManager: Option[ActorRef] = None
def receive: Receive = {
case aRef: ActorRef =>
if (processManager.isEmpty) {
processManager = Some(aRef)
context.watch(aRef) // register to "watch" the process manager
}
case Terminated =>
// process manager was permanently stopped
case ...
}
}
object Demo extends App {
val actorSystem = ActorSystem("my-actor-system")
val notifier = actorSystem.actorOf(Props(classOf[Notifier]))
val processManager = actorSystem.actorOf(Props(classOf[ProcessManager]))
notifier ! processManager // send processManager's ref to the notifier
...
processManager ! "some message which will fail and stop pm actor"
...
}
需要注意的是:在嘗試創建ProcessManager
時拋出ActorInitializationException
之前,可能無法執行DeathWatch
注冊。
如果您需要在ProcessManager
的子ProcessManager
拋出異常時向Notifier
發送消息,則在ProcessManager
覆蓋Supervisor策略並將此消息作為策略的一部分發送。 就像是:
class ProcessManager extends Actor {
import akka.actor.OneForOneStrategy
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case _: ActorInitializationException =>
val notifier = context.actorSelection("/path/to/notifier")
notifier ! CustomErrorMessage
Stop
case _: Exception => Escalate
}
def receive: Receive = {
...
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.