Акка - как сказать системе, что делать после достижения максимальных попыток стратегии?

Предполагая, супервизор актер определил определенную стратегию:

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

И скажем, актеру дали указание возобновить, но он потерпел неудачу в 11-й раз за текущую продолжительность.

Что происходит сейчас?

Является ли родительский актер обостряет проблему?

Может ли он теперь как-то остановить актера упорядоченным способом (например, сказать дочернему актору закрыть соединение с БД)?

Есть ли другой метод overide для вызова в этом случае?

1 ответ

Супервизор актера может отправить сообщение ребенку, чтобы остановить DB, когда он получил сообщение об эскалации от контролируемого актера.

maxNrOfRetries а также withinTimeRange параметры в OneForOneStrategy применять только к restart(); они не вступают в игру для resume(), В вашем случае, если контролируемый ребенок выдает исключение 11 раз, независимо от того, произойдет ли это в течение одной минуты, оно возобновляется 11 раз.

Ваша стратегия наблюдения в первую очередь соответствует Exception, который охватывает самые исключительные условия, которые ваш актер может бросить, в этом случае resume() используется. Стратегия во-вторых соответствует не Exception (т.е. Error), в таком случае escalate() используется. Так что если Error брошен в ребенка, родитель не обостряет проблему.

Для отслеживания количества возобновлений родительский субъект может содержать Map из ActorRef и количество раз, которое ребенок возобновил. Это возможно, потому что sender в стратегии есть ссылка на неудавшегося ребенка. После достижения определенного порога родитель может отправить ребенку сообщение, например, чтобы он очистил ресурсы и остановился сам. Что-то вроде следующего (пример в Scala, но вы можете реализовать его в 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 = ???
}

Вы можете сохранить временную метку со счетчиком, если хотите проверить количество повторений в течение продолжительности.

За restart()Как указано здесь, "дочерний субъект останавливается, если число перезапусков превышает maxNrOfRetries в течение withinTimeRange продолжительность."Если вы перезапустили ребенка вместо того, чтобы возобновить его, вы могли бы поместить логику очистки в ребенка postStop крюк. Когда максимальное количество повторов в пределах временного окна превышено, дочерний элемент останавливается и postStop называется.

Другие вопросы по тегам