2017-08-16 1 views
4

En supposant que l'acteur superviseur a défini une certaine stratégie:Akka - comment indiquer au système quoi faire après que les tentatives maximales de la stratégie aient été atteintes?

private static SupervisorStrategy strategy = 
     new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder. 
       match(Exception.class, e -> resume()). 
       matchAny(o -> escalate()).build()); 

Et permet de dire l'acteur a été chargé de reprendre, mais a échoué pour la 11e fois dans la durée actuelle.

Que se passe-t-il maintenant?

L'acteur parent aggrave-t-il le problème? Peut-il maintenant arrêter l'acteur d'une manière ordonnée (par exemple dire à l'acteur enfant de fermer la connexion à la base de données)?

Y a-t-il une autre méthode d'inversion à appeler dans ce cas?

Répondre

0

Le superviseur de l'acteur peut envoyer un message à l'enfant pour qu'il arrête le DB lorsqu'il a reçu le message escalation de l'acteur supervisé.

0

Les paramètres maxNrOfRetries et withinTimeRange dans OneForOneStrategy s'appliquent uniquement à restart(); ils n'entrent pas en jeu pour resume(). Dans votre cas, si l'enfant supervisé lance une exception 11 fois, peu importe si cela se produit dans une minute, il est repris 11 fois.

Votre stratégie de supervision correspond d'abord au Exception, qui couvre la plupart des conditions exceptionnelles que votre acteur pourrait lancer, auquel cas resume() est utilisé. La stratégie correspond secondement sur un non Exception (c'est-à-dire un Error), auquel cas escalate() est utilisé. Donc, à moins qu'un Error ne soit lancé dans l'enfant, le parent n'élèvera pas le problème.

Pour suivre les comptes de reprise, l'acteur parent peut contenir un Map de ActorRef s et le nombre de fois qu'un enfant a repris. Ceci est possible car sender dans la stratégie est une référence à l'enfant ayant échoué. Une fois qu'un certain seuil a été atteint, le parent peut envoyer un message à l'enfant pour qu'il nettoie les ressources et s'arrête lui-même, par exemple. Quelque chose comme ce qui suit (l'exemple est à Scala, mais vous pouvez le mettre en œuvre en Java):

class Parent extends Actor { 

    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { 
     case _: Exception => 
     val child = sender 
     resumeCounts.get(child) match { 
      case Some(count) if count == resumeMax => 
      child ! StopDB 
      case Some(count) => 
      resumeCounts = resumeCounts + (child -> count + 1) 
      case None => 
      resumeCounts = resumeCounts + (child -> 1) 
     } 
     Resume 
     case _ => Escalate 
    } 

    val resumeMax = 10 
    var resumeCounts: Map[ActorRef, Int] = Map.empty[ActorRef, Int] 

    def receive = ??? 
} 

Vous pouvez enregistrer un horodatage avec le compte si vous voulez vérifier le nombre de reprises dans une durée.

Pour restart(), comme indiqué here, le « acteur enfant est arrêté si le nombre de redémarrage dépasse maxNrOfRetries pendant la durée withinTimeRange. » Si vous avez redémarré l'enfant au lieu de le reprendre, vous pouvez placer la logique de nettoyage dans le crochet postStop de l'enfant. Lorsque le nombre maximal de tentatives dans une fenêtre de temps est dépassé, l'enfant est arrêté et postStop est appelée.