Akka: How to combine OneForOneStrategy and AllForOneStrategy
If I define supervisory strategy for the actor to Scala, how can I use both OneForOneStrategy
and AllForOneStrategy
? Is there an easy way to combine them or should I define a custom one SupervisorStrategy
? Here's an example:
class MyActor extends Actor {
override val supervisorStrategy = OneForOneStrategy() {
case _: NullPointerException => Restart
case _: FileNotFoundException => Restart // here I want to restart all children
case _: Exception => Escalate
}
}
If I need to write my own supervisor strategy, how can I do it? I haven't found an example for this.
source to share
You will need to define a custom supervisor strategy. For your specific use case, the following custom strategy will work:
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)
}
}
}
Here is the gist that tests the above strategy. The BOM creates a supervisor that uses CustomStrategy
and creates two children. When one child ejects NullPointerException
, only that child is restarted; when the child ejects FileNotFoundException
, both children restart.
A few notes on custom strategy:
- It expands
SupervisorStrategy
and simulates after defining existing strategies. - It is defined inside a package
akka.actor
to be able to access its private parts. -
processFailure
, one of the methods that should be overridden in the extending classesSupervisorStrategy
is called onRestart
andStop
, so for your scenario we will define individual behavior there.
source to share