Акка: Как объединить OneForOneStrategy и AllForOneStrategy
Если я определю стратегию супервизора для актера в Scala, как я могу использовать оба OneForOneStrategy
и AllForOneStrategy
? Есть ли простой способ объединить их или мне нужно определить пользовательский SupervisorStrategy
? Вот пример:
class MyActor extends Actor {
override val supervisorStrategy = OneForOneStrategy() {
case _: NullPointerException => Restart
case _: FileNotFoundException => Restart // here I want to restart all children
case _: Exception => Escalate
}
}
Если мне нужно написать собственную стратегию супервизора, как я могу это сделать? Я не нашел примера для этого.
1 ответ
Вы должны будете определить собственную стратегию супервизора. Для вашего конкретного случая использования будет работать следующая пользовательская стратегия:
package akka.actor
import java.io.FileNotFoundException
import scala.concurrent.duration._
case class CustomStrategy(
maxNrOfRetries: Int = -1,
withinTimeRange: Duration = Duration.Inf,
override val loggingEnabled: Boolean = true)(val decider: SupervisorStrategy.Decider)
extends SupervisorStrategy {
import SupervisorStrategy._
private val retriesWindow = (maxNrOfRetriesOption(maxNrOfRetries), withinTimeRangeOption(withinTimeRange).map(_.toMillis.toInt))
def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRef]): Unit = ()
def processFailure(context: ActorContext, restart: Boolean, child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]): Unit = {
if (cause.isInstanceOf[FileNotFoundException]) {
// behave like AllForOneStrategy
if (children.nonEmpty) {
if (restart && children.forall(_.requestRestartPermission(retriesWindow)))
children foreach (crs ⇒ restartChild(crs.child, cause, suspendFirst = (crs.child != child)))
else
for (c ← children) context.stop(c.child)
}
} else {
// behave like OneForOneStrategy
if (restart && stats.requestRestartPermission(retriesWindow))
restartChild(child, cause, suspendFirst = false)
else
context.stop(child)
}
}
}
Вот суть, которая проверяет вышеуказанную стратегию. Спецификация создает супервизор, который использует CustomStrategy
и это создает двух детей. Когда один ребенок бросает NullPointerException
только тот ребенок перезапущен; когда ребенок бросает FileNotFoundException
Оба ребенка перезапускаются.
Несколько замечаний о пользовательской стратегии:
- Расширяется
SupervisorStrategy
и моделируется после существующих стратегий, определенных здесь. - Он определяется внутри
akka.actor
Пакет, чтобы иметь доступ к пакету частных членов там. processFailure
, один из методов, который должен быть переопределен в классах, которые расширяютSupervisorStrategy
называетсяRestart
а такжеStop
так что для вашего сценария мы определяем пользовательское поведение там.