2017-09-14 2 views
1

J'ai une hiérarchie simple acteur qui se présente comme suit:exception dans Propager Akka

root 
    | 
    -- parent1 
    | | 
    | -- child1_1 
    | | 
    | -- child1_2 
    | 
    -- parent2 
     | 
     -- child2_1 
     | 
     -- child2_2 

root met en oeuvre une supervisorStrategy manutention diverses exceptions.
Si une exception non gérée se produit dans parent1 ou parent2 alors supervisorStrategy est atteinte et la gestion est effectuée de façon appropriée.
Si une exception non gérée se produit dans l'un des enfants alors je viens d'obtenir [ERROR] akka.actor.OneForOneStrategy et c'est tout.

Comment puis-je obtenir une erreur non gérée dans la hiérarchie pour propager vers le haut et atteindre le root où il serait géré?

Ai-je besoin de gérer la supervision et d'ajouter Escalate à chaque niveau?

Répondre

1

La stratégie de supervision par défaut est de redémarrer enfant acteur si l'exception est du type Exception (ou ses enfants).

Lorsque la stratégie de superviseur n'est pas défini pour un acteur les exceptions suivantes sont gérées par défaut:

ActorInitializationException arrêtera l'enfant acteur ne

ActorKilledException arrêtera l'enfant acteur ne

DeathPactException va arrêter l'acteur enfant défaillant

Exception redémarrage t il ne enfant acteur

D'autres types de Throwable sera transmise à l'acteur parent

Alors oui, vous avez besoin d'ajouter une stratégie de surveillance à chaque niveau dans ce cas.

Exemple:

import akka.actor.SupervisorStrategy.{Escalate, Restart, Resume, Stop} 
import akka.actor.{Actor, ActorLogging, ActorSystem, OneForOneStrategy, Props} 

import scala.concurrent.duration._ 

class RootActor extends Actor with ActorLogging { 

    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { 
     case _: Exception    => { 
     log.info("Got exception in root") 
     Escalate 
     } 
    } 

    override def receive: Receive = { 
    case "START_ROOT" => 
     log.info("Started root actor") 
     val parentActor = context.actorOf(Props(classOf[ParentActor])) 
     parentActor ! "START_PARENT" 
    } 
} 

class ParentActor extends Actor with ActorLogging { 
    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { 
     case _: Exception    => { 
     log.info("Got exception in parent") 
     Escalate 
     } 
    } 

    override def receive: Receive = { 
    case "START_PARENT" => 
     log.info("Started parent actor") 
     val childActor = context.actorOf(Props(classOf[ChildActor])) 
     childActor ! "START_CHILD" 
    } 
} 

class ChildActor extends Actor with ActorLogging { 
    override def receive: Receive = { 
    case "START_CHILD" => 
     throw new Exception("Exception from CHILD ACTOR") 
     log.info("Started child actor") 
    } 

    override def preRestart(reason: Throwable, message: Option[Any]): Unit = { 
    log.info("Restarting child actor") 
    super.preRestart(reason, message) 
    } 
} 
object App { 
    def main(args: Array[String]): Unit = { 

    val system = ActorSystem("my-system") 
    val rootActor = system.actorOf(Props(classOf[RootActor])) 
    rootActor ! "START_ROOT" 

    } 
} 

Dans ce cas, exception de l'acteur de l'enfant sera transmise à l'acteur racine.