2012-04-28 1 views
10

Quelle est la meilleure façon pour un acteur d'essayer quelque chose de nouveau en cas d'échec, mais avec des intervalles de temps croissants entre les tentatives? Disons que je veux que l'acteur essaie à nouveau après 15 secondes, puis 30 secondes, puis chaque minute pour un nombre limité de fois.Akka: Comment planifier des nouvelles tentatives en cas d'échec avec des intervalles de retard croissants?

Voici ce que je suis venu avec:

  • la méthode de l'acteur qui effectue le travail réel a un paramètre optionnel RetryInfo que, le cas échéant, contient le numéro de la nouvelle tentative, nous sommes actuellement en
  • en cas d'échec, l'acteur lui-même envoyer un nouveau ScheduleRetryMessage avec retryCount + 1, puis jeter un RuntimeException
  • un autre acteur supervise l'acteur des travailleurs, en utilisant new OneForOneStrategy(-1, Duration.Inf() retour Resume comme sa directive. L'acteur n'a pas d'état, donc Resume devrait être OK
  • à la réception du ScheduleRetryMessage, l'acteur
    • si retryCount < MAX_RETRIES: utiliser le planificateur de Akka pour planifier l'envoi d'un RetryMessage après le délai
    • souhaité autre: enfin abandonner, l'envoi d'un message à un autre acteur pour erreur de déclaration

est-ce une bonne solution ou est-il une meilleure approche?

Répondre

8

Vous pourriez avoir un superviseur qui démarre l'acteur travailleur. Le conseil des docs est de déclarer un routeur de taille 1 pour le travailleur. Le superviseur doit garder une trace du nombre de tentatives, puis planifier le message envoyé au travailleur, selon le cas.

Même si vous créeriez une autre couche d'acteurs, cela me semble plus clair puisque vous retirez la fonctionnalité de supervision du travailleur. Idéalement, vous pourriez faire de ce 1 superviseur à n travailleurs, mais je pense que vous devrez utiliser Lifecycle Monitoring pour obtenir un échec d'un acteur enfant. Dans ce cas, vous pouvez simplement garder une carte de [ActorRef, Int] pour garder une trace du nombre de tentatives pour tous les travailleurs supervisés. La politique de supervision reprendrait, mais si vous atteigniez vos tentatives maximum, vous pourriez envoyer une PoisonPill à l'ActorRef fautif.

+0

Idée intéressante, je vais essayer ça. Merci! –

7

Dans ce cas, j'utilise une supervision standard. Un acteur parent/superviseur définit des tentatives dans une fenêtre temporelle. Le nouvel enfant de travail réorganise simplement le message qui a provoqué l'échec avec un délai dans preRestart().

Si le nouvel enfant est plutôt complexe, vous pouvez envisager d'interconnecter un acteur intermédiaire. Cet acteur augmente simplement la supervision. Sur preRestart, l'acteur intermédiaire planifie un message de redémarrage (retardé). Lorsque l'acteur intermédiaire a conservé son état, il peut simplement redémarrer l'acteur travailleur (avec retard).

Comme vous pouvez le voir, la partie retardée peut être dans preRestart ou au démarrage du worker.

Questions connexes