diff --git a/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala index 78fd2a6780..781b227f6c 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala @@ -23,7 +23,7 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout import DeathWatchSpec._ - lazy val supervisor = system.actorOf(Props(new Supervisor(FaultHandlingStrategy.defaultFaultHandler)), "watchers") + lazy val supervisor = system.actorOf(Props(new Supervisor(SupervisorStrategy.defaultStrategy)), "watchers") def startWatching(target: ActorRef) = Await.result((supervisor ? props(target, testActor)).mapTo[ActorRef], 3 seconds) @@ -115,7 +115,7 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout "fail a monitor which does not handle Terminated()" in { filterEvents(EventFilter[ActorKilledException](), EventFilter[DeathPactException]()) { case class FF(fail: Failed) - val strategy = new OneForOneStrategy(FaultHandlingStrategy.makeDecider(List(classOf[Exception])), Some(0)) { + val strategy = new OneForOneStrategy(SupervisorStrategy.makeDecider(List(classOf[Exception])), Some(0)) { override def handleFailure(context: ActorContext, child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]) = { testActor.tell(FF(Failed(cause)), child) super.handleFailure(context, child, cause, stats, children) diff --git a/akka-actor-tests/src/test/scala/akka/actor/Supervisor.scala b/akka-actor-tests/src/test/scala/akka/actor/Supervisor.scala index d04990c375..80524ea9dc 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/Supervisor.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/Supervisor.scala @@ -7,7 +7,7 @@ package akka.actor * For testing Supervisor behavior, normally you don't supply the strategy * from the outside like this. */ -class Supervisor(override val supervisorStrategy: FaultHandlingStrategy) extends Actor { +class Supervisor(override val supervisorStrategy: SupervisorStrategy) extends Actor { def receive = { case x: Props ⇒ sender ! context.actorOf(x) diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala index 2fc5996b54..d0be683c94 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala @@ -16,7 +16,7 @@ object SupervisorHierarchySpec { * For testing Supervisor behavior, normally you don't supply the strategy * from the outside like this. */ - class CountDownActor(countDown: CountDownLatch, override val supervisorStrategy: FaultHandlingStrategy) extends Actor { + class CountDownActor(countDown: CountDownLatch, override val supervisorStrategy: SupervisorStrategy) extends Actor { protected def receive = { case p: Props ⇒ sender ! context.actorOf(p) @@ -43,7 +43,7 @@ class SupervisorHierarchySpec extends AkkaSpec with DefaultTimeout { val managerProps = Props(new CountDownActor(countDown, AllForOneStrategy(List(), None, None))) val manager = Await.result((boss ? managerProps).mapTo[ActorRef], timeout.duration) - val workerProps = Props(new CountDownActor(countDown, FaultHandlingStrategy.defaultFaultHandler)) + val workerProps = Props(new CountDownActor(countDown, SupervisorStrategy.defaultStrategy)) val workerOne, workerTwo, workerThree = Await.result((manager ? workerProps).mapTo[ActorRef], timeout.duration) filterException[ActorKilledException] { @@ -62,7 +62,7 @@ class SupervisorHierarchySpec extends AkkaSpec with DefaultTimeout { val boss = system.actorOf(Props(new Actor { override val supervisorStrategy = OneForOneStrategy(List(classOf[Throwable]), 1, 5000) - val crasher = context.watch(context.actorOf(Props(new CountDownActor(countDownMessages, FaultHandlingStrategy.defaultFaultHandler)))) + val crasher = context.watch(context.actorOf(Props(new CountDownActor(countDownMessages, SupervisorStrategy.defaultStrategy)))) protected def receive = { case "killCrasher" ⇒ crasher ! Kill diff --git a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala index 6ef7608ce2..92cec0a79f 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala @@ -300,7 +300,7 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config) filterEvents(EventFilter[IllegalStateException]("expected")) { val boss = system.actorOf(Props(new Actor { override val supervisorStrategy = OneForOneStrategy { - case e: IllegalStateException if e.getMessage == "expected" ⇒ FaultHandlingStrategy.Resume + case e: IllegalStateException if e.getMessage == "expected" ⇒ SupervisorStrategy.Resume } def receive = { case p: TypedProps[_] ⇒ context.sender ! TypedActor(context).typedActorOf(p) diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index f48b367e56..40b590aa51 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -236,7 +236,7 @@ trait Actor { * User overridable definition the strategy to use for supervising * child actors. */ - def supervisorStrategy(): FaultHandlingStrategy = FaultHandlingStrategy.defaultFaultHandler + def supervisorStrategy(): SupervisorStrategy = SupervisorStrategy.defaultStrategy /** * User overridable callback. diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 0da5c13e1d..49f241d0c6 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -336,7 +336,7 @@ class LocalActorRefProvider( private class Guardian extends Actor { override val supervisorStrategy = { - import akka.actor.FaultHandlingStrategy._ + import akka.actor.SupervisorStrategy._ OneForOneStrategy { case _: ActorKilledException ⇒ Stop case _: ActorInitializationException ⇒ Stop @@ -376,8 +376,6 @@ class LocalActorRefProvider( override def preRestart(cause: Throwable, msg: Option[Any]) {} } - private val guardianProps = Props(new Guardian) - /* * The problem is that ActorRefs need a reference to the ActorSystem to * provide their service. Hence they cannot be created while the @@ -403,6 +401,8 @@ class LocalActorRefProvider( */ def registerExtraNames(_extras: Map[String, InternalActorRef]): Unit = extraNames ++= _extras + private val guardianProps = Props(new Guardian) + lazy val rootGuardian: InternalActorRef = new LocalActorRef(system, guardianProps, theOneWhoWalksTheBubblesOfSpaceTime, rootPath, true) { object Extra { diff --git a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala index 02c94a34bc..e7ae22f57f 100644 --- a/akka-actor/src/main/scala/akka/actor/FaultHandling.scala +++ b/akka-actor/src/main/scala/akka/actor/FaultHandling.scala @@ -44,7 +44,7 @@ case class ChildRestartStats(val child: ActorRef, var maxNrOfRetriesCount: Int = } } -object FaultHandlingStrategy { +object SupervisorStrategy { sealed trait Action /** @@ -95,7 +95,7 @@ object FaultHandlingStrategy { */ def escalate = Escalate - final val defaultFaultHandler: FaultHandlingStrategy = { + final val defaultStrategy: SupervisorStrategy = { def defaultDecider: Decider = { case _: ActorInitializationException ⇒ Stop case _: ActorKilledException ⇒ Stop @@ -158,9 +158,9 @@ object FaultHandlingStrategy { } } -abstract class FaultHandlingStrategy { +abstract class SupervisorStrategy { - import FaultHandlingStrategy._ + import SupervisorStrategy._ def decider: Decider @@ -200,12 +200,12 @@ abstract class FaultHandlingStrategy { object AllForOneStrategy { def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): AllForOneStrategy = - new AllForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), + new AllForOneStrategy(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): AllForOneStrategy = - new AllForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), maxNrOfRetries, withinTimeRange) + new AllForOneStrategy(SupervisorStrategy.makeDecider(trapExit), maxNrOfRetries, withinTimeRange) def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Option[Int]): AllForOneStrategy = - new AllForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), maxNrOfRetries, None) + new AllForOneStrategy(SupervisorStrategy.makeDecider(trapExit), maxNrOfRetries, None) } /** @@ -214,22 +214,22 @@ object AllForOneStrategy { * maxNrOfRetries = the number of times an actor is allowed to be restarted * withinTimeRange = millisecond time window for maxNrOfRetries, negative means no window */ -case class AllForOneStrategy(decider: FaultHandlingStrategy.Decider, +case class AllForOneStrategy(decider: SupervisorStrategy.Decider, maxNrOfRetries: Option[Int] = None, - withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy { + withinTimeRange: Option[Int] = None) extends SupervisorStrategy { - def this(decider: FaultHandlingStrategy.JDecider, maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(decider), + def this(decider: SupervisorStrategy.JDecider, maxNrOfRetries: Int, withinTimeRange: Int) = + this(SupervisorStrategy.makeDecider(decider), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def this(trapExit: JIterable[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(trapExit), + this(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(trapExit), + this(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) @@ -257,12 +257,12 @@ case class AllForOneStrategy(decider: FaultHandlingStrategy.Decider, object OneForOneStrategy { def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int): OneForOneStrategy = - new OneForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), + new OneForOneStrategy(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Option[Int], withinTimeRange: Option[Int]): OneForOneStrategy = - new OneForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), maxNrOfRetries, withinTimeRange) + new OneForOneStrategy(SupervisorStrategy.makeDecider(trapExit), maxNrOfRetries, withinTimeRange) def apply(trapExit: List[Class[_ <: Throwable]], maxNrOfRetries: Option[Int]): OneForOneStrategy = - new OneForOneStrategy(FaultHandlingStrategy.makeDecider(trapExit), maxNrOfRetries, None) + new OneForOneStrategy(SupervisorStrategy.makeDecider(trapExit), maxNrOfRetries, None) } /** @@ -271,22 +271,22 @@ object OneForOneStrategy { * maxNrOfRetries = the number of times an actor is allowed to be restarted * withinTimeRange = millisecond time window for maxNrOfRetries, negative means no window */ -case class OneForOneStrategy(decider: FaultHandlingStrategy.Decider, +case class OneForOneStrategy(decider: SupervisorStrategy.Decider, maxNrOfRetries: Option[Int] = None, - withinTimeRange: Option[Int] = None) extends FaultHandlingStrategy { + withinTimeRange: Option[Int] = None) extends SupervisorStrategy { - def this(decider: FaultHandlingStrategy.JDecider, maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(decider), + def this(decider: SupervisorStrategy.JDecider, maxNrOfRetries: Int, withinTimeRange: Int) = + this(SupervisorStrategy.makeDecider(decider), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def this(trapExit: JIterable[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(trapExit), + this(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) def this(trapExit: Array[Class[_ <: Throwable]], maxNrOfRetries: Int, withinTimeRange: Int) = - this(FaultHandlingStrategy.makeDecider(trapExit), + this(SupervisorStrategy.makeDecider(trapExit), if (maxNrOfRetries < 0) None else Some(maxNrOfRetries), if (withinTimeRange < 0) None else Some(withinTimeRange)) diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala index 9f81f4c754..3bafe9ba4e 100644 --- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala @@ -218,9 +218,9 @@ object TypedActor extends ExtensionId[TypedActorExtension] with ExtensionIdProvi TypedActor.currentContext set null } - override def supervisorStrategy: FaultHandlingStrategy = me match { - case l: SupervisorStrategy ⇒ l.supervisorStrategy - case _ ⇒ super.supervisorStrategy + override def supervisorStrategy(): SupervisorStrategy = me match { + case l: Supervisor ⇒ l.supervisorStrategy + case _ ⇒ super.supervisorStrategy } override def preStart(): Unit = me match { @@ -283,12 +283,12 @@ object TypedActor extends ExtensionId[TypedActorExtension] with ExtensionIdProvi /** * Mix this into your TypedActor to be able to define supervisor strategy */ - trait SupervisorStrategy { + trait Supervisor { /** * User overridable definition the strategy to use for supervising * child actors. */ - def supervisorStrategy: FaultHandlingStrategy = FaultHandlingStrategy.defaultFaultHandler + def supervisorStrategy(): SupervisorStrategy = SupervisorStrategy.defaultStrategy } /** diff --git a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala index 69cb096e26..ba677b750b 100644 --- a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala @@ -37,7 +37,7 @@ import akka.dispatch.{ MessageDispatcher, Promise } * } * } * - * private static FaultHandlingStrategy strategy = new OneForOneStrategy(new Function() { + * private static SupervisorStrategy strategy = new OneForOneStrategy(new Function() { * @Override * public Action apply(Throwable t) { * if (t instanceof ArithmeticException) { @@ -53,7 +53,7 @@ import akka.dispatch.{ MessageDispatcher, Promise } * }, 10, 60000); * * @Override - * public FaultHandlingStrategy supervisorStrategy() { + * public SupervisorStrategy supervisorStrategy() { * return strategy; * } * @@ -116,7 +116,7 @@ abstract class UntypedActor extends Actor { * User overridable definition the strategy to use for supervising * child actors. */ - override def supervisorStrategy(): FaultHandlingStrategy = super.supervisorStrategy() + override def supervisorStrategy(): SupervisorStrategy = super.supervisorStrategy() /** * User overridable callback. diff --git a/akka-docs/general/actors.rst b/akka-docs/general/actors.rst index 2de931565d..952b1b08e4 100644 --- a/akka-docs/general/actors.rst +++ b/akka-docs/general/actors.rst @@ -3,123 +3,121 @@ What is an Actor? ================= -The previous section about :ref:`actor-systems` explained how actors form -hierarchies and are the smallest unit when building an application. This -section looks at one such actor in isolation, explaining the concepts you -encounter while implementing it. For more an in depth reference with all the +The previous section about :ref:`actor-systems` explained how actors form +hierarchies and are the smallest unit when building an application. This +section looks at one such actor in isolation, explaining the concepts you +encounter while implementing it. For more an in depth reference with all the details please refer to :ref:`actors-scala` and :ref:`untyped-actors-java`. -An actor is a container for `State`_, `Behavior`_, a `Mailbox`_, `Children`_ -and a `Fault Handling Strategy`_. All of this is encapsulated behind an `Actor +An actor is a container for `State`_, `Behavior`_, a `Mailbox`_, `Children`_ +and a `Supervisor Strategy`_. All of this is encapsulated behind an `Actor Reference`_. Finally, this happens `When an Actor Terminates`_. Actor Reference --------------- -As detailed below, an actor object needs to be shielded from the outside in -order to benefit from the actor model. Therefore, actors are represented to the -outside using actor references, which are objects that can be passed around -freely and without restriction. This split into inner and outer object enables -transparency for all the desired operations: restarting an actor without -needing to update references elsewhere, placing the actual actor object on -remote hosts, sending messages to actors in completely different applications. -But the most important aspect is that it is not possible to look inside an -actor and get hold of its state from the outside, unless the actor unwisely +As detailed below, an actor object needs to be shielded from the outside in +order to benefit from the actor model. Therefore, actors are represented to the +outside using actor references, which are objects that can be passed around +freely and without restriction. This split into inner and outer object enables +transparency for all the desired operations: restarting an actor without +needing to update references elsewhere, placing the actual actor object on +remote hosts, sending messages to actors in completely different applications. +But the most important aspect is that it is not possible to look inside an +actor and get hold of its state from the outside, unless the actor unwisely publishes this information itself. State ----- -Actor objects will typically contain some variables which reflect possible -states the actor may be in. This can be an explicit state machine (e.g. using -the :ref:`fsm` module), or it could be a counter, set of listeners, pending -requests, etc. These data are what make an actor valuable, and they must be -protected from corruption by other actors. The good news is that Akka actors -conceptually each have their own light-weight thread, which is completely -shielded from the rest of the system. This means that instead of having to -synchronize access using locks you can just write your actor code without +Actor objects will typically contain some variables which reflect possible +states the actor may be in. This can be an explicit state machine (e.g. using +the :ref:`fsm` module), or it could be a counter, set of listeners, pending +requests, etc. These data are what make an actor valuable, and they must be +protected from corruption by other actors. The good news is that Akka actors +conceptually each have their own light-weight thread, which is completely +shielded from the rest of the system. This means that instead of having to +synchronize access using locks you can just write your actor code without worrying about concurrency at all. -Behind the scenes Akka will run sets of actors on sets of real threads, where -typically many actors share one thread, and subsequent invocations of one actor -may end up being processed on different threads. Akka ensures that this -implementation detail does not affect the single-threadedness of handling the +Behind the scenes Akka will run sets of actors on sets of real threads, where +typically many actors share one thread, and subsequent invocations of one actor +may end up being processed on different threads. Akka ensures that this +implementation detail does not affect the single-threadedness of handling the actor’s state. -Because the internal state is vital to an actor’s operations, having -inconsistent state is fatal. Thus, when the actor fails and is restarted by its -supervisor, the state will be created from scratch, like upon first creating +Because the internal state is vital to an actor’s operations, having +inconsistent state is fatal. Thus, when the actor fails and is restarted by its +supervisor, the state will be created from scratch, like upon first creating the actor. This is to enable the ability of self-healing of the system. Behavior -------- -Every time a message is processed, it is matched against the current behavior -of the actor. Behavior means a function which defines the actions to be taken -in reaction to the message at that point in time, say forward a request if the -client is authorized, deny it otherwise. This behavior may change over time, -e.g. because different clients obtain authorization over time, or because the -actor may go into an “out-of-service” mode and later come back. These changes -are achieved by either encoding them in state variables which are read from the -behavior logic, or the function itself may be swapped out at runtime, see the -``become`` and ``unbecome`` operations. However, the initial behavior defined -during construction of the actor object is special in the sense that a restart +Every time a message is processed, it is matched against the current behavior +of the actor. Behavior means a function which defines the actions to be taken +in reaction to the message at that point in time, say forward a request if the +client is authorized, deny it otherwise. This behavior may change over time, +e.g. because different clients obtain authorization over time, or because the +actor may go into an “out-of-service” mode and later come back. These changes +are achieved by either encoding them in state variables which are read from the +behavior logic, or the function itself may be swapped out at runtime, see the +``become`` and ``unbecome`` operations. However, the initial behavior defined +during construction of the actor object is special in the sense that a restart of the actor will reset its behavior to this initial one. Mailbox ------- -An actor’s purpose is the processing of messages, and these messages were sent -to the actor from other actors (or from outside the actor system). The piece -which connects sender and receiver is the actor’s mailbox: each actor has -exactly one mailbox to which all senders enqueue their messages. Enqueuing -happens in the time-order of send operations, which means that messages sent -from different actors may not have a defined order at runtime due to the -apparent randomness of distributing actors across threads. Sending multiple -messages to the same target from the same actor, on the other hand, will +An actor’s purpose is the processing of messages, and these messages were sent +to the actor from other actors (or from outside the actor system). The piece +which connects sender and receiver is the actor’s mailbox: each actor has +exactly one mailbox to which all senders enqueue their messages. Enqueuing +happens in the time-order of send operations, which means that messages sent +from different actors may not have a defined order at runtime due to the +apparent randomness of distributing actors across threads. Sending multiple +messages to the same target from the same actor, on the other hand, will enqueue them in the same order. -There are different mailbox implementations to choose from, the default being a -FIFO: the order of the messages processed by the actor matches the order in -which they were enqueued. This is usually a good default, but applications may -need to prioritize some messages over others. In this case, a priority mailbox -will enqueue not always at the end but at a position as given by the message -priority, which might even be at the front. While using such a queue, the order -of messages processed will naturally be defined by the queue’s algorithm and in +There are different mailbox implementations to choose from, the default being a +FIFO: the order of the messages processed by the actor matches the order in +which they were enqueued. This is usually a good default, but applications may +need to prioritize some messages over others. In this case, a priority mailbox +will enqueue not always at the end but at a position as given by the message +priority, which might even be at the front. While using such a queue, the order +of messages processed will naturally be defined by the queue’s algorithm and in general not be FIFO. -An important feature in which Akka differs from some other actor model -implementations is that the current behavior must always handle the next -dequeued message, there is no scanning the mailbox for the next matching one. -Failure to handle a message will typically be treated as a failure, unless this +An important feature in which Akka differs from some other actor model +implementations is that the current behavior must always handle the next +dequeued message, there is no scanning the mailbox for the next matching one. +Failure to handle a message will typically be treated as a failure, unless this behavior is overridden. Children -------- -Each actor is potentially a supervisor: if it creates children for delegating -sub-tasks, it will automatically supervise them. The list of children is -maintained within the actor’s context and the actor has access to it. -Modifications to the list are done by creating (``context.actorOf(...)``) or -stopping (``context.stop(child)``) children and these actions are reflected -immediately. The actual creation and termination actions happen behind the +Each actor is potentially a supervisor: if it creates children for delegating +sub-tasks, it will automatically supervise them. The list of children is +maintained within the actor’s context and the actor has access to it. +Modifications to the list are done by creating (``context.actorOf(...)``) or +stopping (``context.stop(child)``) children and these actions are reflected +immediately. The actual creation and termination actions happen behind the scenes in an asynchronous way, so they do not “block” their supervisor. -Fault Handling Strategy ------------------------ +Supervisor Strategy +------------------- -The final piece of an actor is its strategy for handling faults of its -children. To keep it simple and robust, this is declared outside of the actor’s -code and has no access to the actor’s state. Fault handling is then done -transparently by Akka, applying one of the strategies described in -:ref:`supervision` for each incoming failure. As this strategy is fundamental -to how an actor system is structured, it cannot be changed once an actor has -been created. +The final piece of an actor is its strategy for handling faults of its +children. Fault handling is then done transparently by Akka, applying one +of the strategies described in :ref:`supervision` for each incoming failure. +As this strategy is fundamental to how an actor system is structured, it +cannot be changed once an actor has been created. -Considering that there is only one such strategy for each actor, this means -that if different strategies apply to the various children of an actor, the -children should be grouped beneath intermediate supervisors with matching -strategies, preferring once more the structuring of actor systems according to +Considering that there is only one such strategy for each actor, this means +that if different strategies apply to the various children of an actor, the +children should be grouped beneath intermediate supervisors with matching +strategies, preferring once more the structuring of actor systems according to the splitting of tasks into sub-tasks. When an Actor Terminates diff --git a/akka-docs/java/code/akka/docs/actor/FaultHandlingTestBase.java b/akka-docs/java/code/akka/docs/actor/FaultHandlingTestBase.java index 87610a2aef..2ed0c3d715 100644 --- a/akka-docs/java/code/akka/docs/actor/FaultHandlingTestBase.java +++ b/akka-docs/java/code/akka/docs/actor/FaultHandlingTestBase.java @@ -6,8 +6,8 @@ package akka.docs.actor; //#testkit import akka.actor.ActorRef; import akka.actor.ActorSystem; -import akka.actor.FaultHandlingStrategy; -import static akka.actor.FaultHandlingStrategy.*; +import akka.actor.SupervisorStrategy; +import static akka.actor.SupervisorStrategy.*; import akka.actor.OneForOneStrategy; import akka.actor.Props; import akka.actor.Terminated; @@ -38,7 +38,7 @@ public class FaultHandlingTestBase { static public class Supervisor extends UntypedActor { //#strategy - private static FaultHandlingStrategy strategy = new OneForOneStrategy(new Function() { + private static SupervisorStrategy strategy = new OneForOneStrategy(new Function() { @Override public Action apply(Throwable t) { if (t instanceof ArithmeticException) { @@ -54,7 +54,7 @@ public class FaultHandlingTestBase { }, 10, 60000); @Override - public FaultHandlingStrategy supervisorStrategy() { + public SupervisorStrategy supervisorStrategy() { return strategy; } @@ -75,7 +75,7 @@ public class FaultHandlingTestBase { static public class Supervisor2 extends UntypedActor { //#strategy2 - private static FaultHandlingStrategy strategy = new OneForOneStrategy(new Function() { + private static SupervisorStrategy strategy = new OneForOneStrategy(new Function() { @Override public Action apply(Throwable t) { if (t instanceof ArithmeticException) { @@ -91,7 +91,7 @@ public class FaultHandlingTestBase { }, 10, 60000); @Override - public FaultHandlingStrategy supervisorStrategy() { + public SupervisorStrategy supervisorStrategy() { return strategy; } @@ -147,7 +147,7 @@ public class FaultHandlingTestBase { } @Test - public void mustEmployFaultHandler() { + public void mustEmploySupervisorStrategy() { // code here //#testkit EventFilter ex1 = (EventFilter) new ErrorFilter(ArithmeticException.class); diff --git a/akka-docs/java/fault-tolerance.rst b/akka-docs/java/fault-tolerance.rst index 4d0b1abe8c..1f62f77875 100644 --- a/akka-docs/java/fault-tolerance.rst +++ b/akka-docs/java/fault-tolerance.rst @@ -1,7 +1,7 @@ .. _fault-tolerance-java: -Fault Handling Strategies (Java) -================================= +Fault Tolerance (Java) +====================== .. sidebar:: Contents @@ -12,8 +12,8 @@ children, and as such each actor defines fault handling supervisor strategy. This strategy cannot be changed afterwards as it is an integral part of the actor system’s structure. -Creating a Fault Handling Strategy ----------------------------------- +Creating a Supervisor Strategy +------------------------------ For the sake of demonstration let us consider the following strategy: diff --git a/akka-docs/java/typed-actors.rst b/akka-docs/java/typed-actors.rst index 4b7de5ee09..d6b016e3b5 100644 --- a/akka-docs/java/typed-actors.rst +++ b/akka-docs/java/typed-actors.rst @@ -30,7 +30,7 @@ it's located in ``akka.actor.TypedActor``. :include: typed-actor-extension-tools .. warning:: - + Same as not exposing ``this`` of an Akka Actor, it's important not to expose ``this`` of a Typed Actor, instead you should pass the external proxy reference, which is obtained from within your Typed Actor as ``TypedActor.self()``, this is your external identity, as the ``ActorRef`` is the external identity of @@ -127,7 +127,7 @@ Request-reply-with-future message send .. includecode:: code/akka/docs/actor/TypedActorDocTestBase.java :include: typed-actor-call-future -This call is asynchronous, and the Future returned can be used for asynchronous composition. +This call is asynchronous, and the Future returned can be used for asynchronous composition. Stopping Typed Actors --------------------- @@ -153,6 +153,13 @@ you can create child Typed Actors by invoking ``typedActorOf(..)`` on that. This also works for creating child Typed Actors in regular Akka Actors. +Supervisor Strategy +------------------- + +By having your Typed Actor implementation class implement ``TypedActor.Supervisor`` +you can define the strategy to use for supervising child actors, as described in +:ref:`supervision` and :ref:`fault-tolerance-java`. + Lifecycle callbacks ------------------- diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index 7e0d788590..fa8b83db71 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -129,6 +129,7 @@ In addition, it offers: * :obj:`getSelf()` reference to the :class:`ActorRef` of the actor * :obj:`getSender()` reference sender Actor of the last received message, typically used as described in :ref:`UntypedActor.Reply` +* :obj:`supervisorStrategy()` user overridable definition the strategy to use for supervising child actors * :obj:`getContext()` exposes contextual information for the actor and the current message, such as: * factory methods to create child actors (:meth:`actorOf`) diff --git a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst index a3f874894d..6199105e0f 100644 --- a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst +++ b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst @@ -403,7 +403,7 @@ v2.0:: context.parent -*Fault handling strategy* +*Supervisor Strategy* v1.3:: @@ -420,14 +420,18 @@ v1.3:: v2.0:: - val strategy = OneForOneStrategy({ - case _: ArithmeticException ⇒ Resume - case _: NullPointerException ⇒ Restart - case _: IllegalArgumentException ⇒ Stop - case _: Exception ⇒ Escalate - }: Decider, maxNrOfRetries = Some(10), withinTimeRange = Some(60000)) + class MyActor extends Actor { + override val supervisorStrategy = OneForOneStrategy({ + case _: ArithmeticException ⇒ Resume + case _: NullPointerException ⇒ Restart + case _: IllegalArgumentException ⇒ Stop + case _: Exception ⇒ Escalate + }: Decider, maxNrOfRetries = Some(10), withinTimeRange = Some(60000)) - val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(strategy), "supervisor") + def receive = { + case x => + } + } Documentation: diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 558b50fac8..61b49c856f 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -154,6 +154,7 @@ In addition, it offers: * :obj:`self` reference to the :class:`ActorRef` of the actor * :obj:`sender` reference sender Actor of the last received message, typically used as described in :ref:`Actor.Reply` +* :obj:`supervisorStrategy` user overridable definition the strategy to use for supervising child actors * :obj:`context` exposes contextual information for the actor and the current message, such as: * factory methods to create child actors (:meth:`actorOf`) diff --git a/akka-docs/scala/code/akka/docs/actor/FaultHandlingDocSpec.scala b/akka-docs/scala/code/akka/docs/actor/FaultHandlingDocSpec.scala index dc9159de43..22790d2110 100644 --- a/akka-docs/scala/code/akka/docs/actor/FaultHandlingDocSpec.scala +++ b/akka-docs/scala/code/akka/docs/actor/FaultHandlingDocSpec.scala @@ -19,7 +19,7 @@ object FaultHandlingDocSpec { class Supervisor extends Actor { //#strategy import akka.actor.OneForOneStrategy - import akka.actor.FaultHandlingStrategy._ + import akka.actor.SupervisorStrategy._ override val supervisorStrategy = OneForOneStrategy({ case _: ArithmeticException ⇒ Resume @@ -39,7 +39,7 @@ object FaultHandlingDocSpec { class Supervisor2 extends Actor { //#strategy2 import akka.actor.OneForOneStrategy - import akka.actor.FaultHandlingStrategy._ + import akka.actor.SupervisorStrategy._ override val supervisorStrategy = OneForOneStrategy({ case _: ArithmeticException ⇒ Resume diff --git a/akka-docs/scala/fault-tolerance.rst b/akka-docs/scala/fault-tolerance.rst index a4cdd584f0..f17cab2bb3 100644 --- a/akka-docs/scala/fault-tolerance.rst +++ b/akka-docs/scala/fault-tolerance.rst @@ -1,7 +1,7 @@ .. _fault-tolerance-scala: -Fault Handling Strategies (Scala) -================================= +Fault Tolerance (Scala) +======================= .. sidebar:: Contents @@ -12,8 +12,8 @@ children, and as such each actor defines fault handling supervisor strategy. This strategy cannot be changed afterwards as it is an integral part of the actor system’s structure. -Creating a Fault Handling Strategy ----------------------------------- +Creating a Supervisor Strategy +------------------------------ For the sake of demonstration let us consider the following strategy: diff --git a/akka-docs/scala/typed-actors.rst b/akka-docs/scala/typed-actors.rst index 7a5a87aeb4..ba326b8a27 100644 --- a/akka-docs/scala/typed-actors.rst +++ b/akka-docs/scala/typed-actors.rst @@ -30,7 +30,7 @@ it's located in ``akka.actor.TypedActor``. :include: typed-actor-extension-tools .. warning:: - + Same as not exposing ``this`` of an Akka Actor, it's important not to expose ``this`` of a Typed Actor, instead you should pass the external proxy reference, which is obtained from within your Typed Actor as ``TypedActor.self``, this is your external identity, as the ``ActorRef`` is the external identity of @@ -127,7 +127,7 @@ Request-reply-with-future message send .. includecode:: code/akka/docs/actor/TypedActorDocSpec.scala :include: typed-actor-call-future -This call is asynchronous, and the Future returned can be used for asynchronous composition. +This call is asynchronous, and the Future returned can be used for asynchronous composition. Stopping Typed Actors --------------------- @@ -153,6 +153,13 @@ you can create child Typed Actors by invoking ``typedActorOf(..)`` on that. This also works for creating child Typed Actors in regular Akka Actors. +Supervisor Strategy +------------------- + +By having your Typed Actor implementation class implement ``TypedActor.Supervisor`` +you can define the strategy to use for supervising child actors, as described in +:ref:`supervision` and :ref:`fault-tolerance-scala`. + Lifecycle callbacks -------------------