Supervisor
Handling errors and supervising child actors are core functionalities of the Akka Actor model. The supervision strategy allows a parent actor to decide how to handle errors thrown by its children, making the system more resilient. Let's dive into how you can implement a parent actor and manage error handling in an Akka system.
Understanding Supervision Strategies
In Akka, when an actor throws an exception, it's suspended and the supervision strategy of its parent actor is invoked. The parent can decide to: - Resume the child actor, keeping its internal state. - Restart the child actor, resetting its internal state. - Stop the child actor permanently. - Escalate the failure, causing the parent itself to stop and be supervised by its own parent.
Step 1: Setting Up Your Project
First, ensure your build.sbt
file includes dependencies for Akka Typed:
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.15"
)
Step 2: Defining the Child Actor
Create a simple child actor that can throw an exception based on a received message. This example defines a Worker
actor that supports DoWork
and Fail
messages:
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.Behavior
object Worker {
sealed trait Command
case object DoWork extends Command
case object Fail extends Command
def apply(): Behavior[Command] = Behaviors.receiveMessage {
case DoWork =>
println("Worker is doing work")
Behaviors.same
case Fail =>
throw new RuntimeException("Worker failed")
}
}
Step 3: Creating the Parent Actor with Supervision Strategy
Define a parent actor that creates the Worker
actor and specifies a supervision strategy for it. This example uses a supervision strategy to restart the child actor upon failure:
import akka.actor.typed.ActorSystem
import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.Behaviors
object Supervisor {
def apply(): Behavior[Worker.Command] = Behaviors
.supervise[Worker.Command] {
Behaviors.setup { context =>
val worker = context.spawn(Worker(), "workerActor")
// Example: sending messages to the worker
worker ! Worker.DoWork
worker ! Worker.Fail // This will cause the worker to throw an exception
Behaviors.receiveMessage { message =>
worker ! message
Behaviors.same
}
}
}
.onFailure[Exception](SupervisorStrategy.restart) // Supervision strategy to restart the child
}
Step 4: Running the System
Create and run an ActorSystem
with the Supervisor
actor:
object Main extends App {
val system: ActorSystem[Worker.Command] = ActorSystem(Supervisor(), "supervisorSystem")
// Optionally, interact with the system
// e.g., system ! Worker.DoWork
}
Observing Behavior
When the Worker
actor throws an exception due to the Fail
message:
- The parent's supervision strategy is invoked.
- The strategy decides to restart the Worker
actor.
- The Worker
actor's state is reset, and it's ready to receive messages again.
Conclusion
This tutorial introduced the basics of actor supervision in Akka. Supervision strategies empower you to build resilient systems by effectively managing failures. Experimenting with different strategies and understanding their impact on actor states is crucial for leveraging Akka's full potential for building fault-tolerant systems.