2017-07-20 16 views
1

私は2人の俳優があります。システム内のいくつかのプロセスを処理Akka:他の(子供以外の)俳優の中のある俳優の失敗をどうやって捉えることができますか?

ProcessManager(例えば、ユーザ登録、購入、など)

通知 - いくつかのエラーがProcessManagerで発生した場合、ユーザーに通知する必要がありますが。 ProcessManagerアクターの失敗を捕捉する必要があります(たとえば、ActorInitializationExceptionや最大再起動時間に達し、プロセスマネージャーのアクターが停止したなど、何らかの理由で失敗して停止しました)。

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.")) 
     } 
    } 

にはどうすれば通知俳優の内側ProcessManager俳優の(障害のために)終了をキャッチすることができますか?

EDIT 私の問題の背景を説明しましょう。

私はPlayコントローラでPMアクタを作成し、それにメッセージを送信して(Tell)、すぐにユーザにOk応答を返します。 PMアクターが別の子アクターを作成し、作成中にActorInitializationExceptionがスローされます。私はNotifierアクタを使用して(Webソケット経由で)ユーザに通知する必要があります。

答えて

3

あなたはProcessManager俳優が恒久的に停止したときTerminatedメッセージの受信のためのNotifier俳優を登録するDeathWatchを使用することができます。 Notifierは、DeathWatchProcessManager俳優への参照が必要です。そのための方法の1つは、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" 
    ... 
} 

1つの警告:ActorInitializationExceptionがスローされる前にProcessManagerを作成しようとしたときDeathWatch登録が発生することは可能ではないかもしれません。


あなたがProcessManagerの子が例外をスローしたときNotifierにメッセージを送信する必要がある場合は、ProcessManagerのスーパーバイザ戦略をオーバーライドし、戦略の一環として、このメッセージを送信します。何かのように:

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 = { 
    ... 
    } 
} 
+0

私の問題の文脈を説明させてください。私はPlayのコントローラーにPMの俳優を作り、それにメッセージを送る(Tell)、そしてすぐにユーザーにOk応答を返します。 PMアクターが別の子アクターを作成し、作成中にActorInitializationExceptionがスローされます。私はNotifierアクタを使用して(Webソケット経由で)ユーザに通知する必要があります。このソリューションはこの問題を解決しませんが、ありがとうございます。 – Teimuraz

+0

@moreo:更新されました。 – chunjef

関連する問題