diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala index 52b50491ee..444f5087da 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala @@ -142,5 +142,21 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul } } + "have access to the failing child’s reference in supervisorStrategy" in { + val parent = system.actorOf(Props(new Actor { + override val supervisorStrategy = OneForOneStrategy() { + case _: Exception ⇒ testActor ! sender; SupervisorStrategy.Stop + } + def receive = { + case "doit" ⇒ context.actorOf(Props.empty, "child") ! Kill + } + })) + EventFilter[ActorKilledException](occurrences = 1) intercept { + parent ! "doit" + } + val p = expectMsgType[ActorRef].path + p.parent must be === parent.path + p.name must be === "child" + } } } diff --git a/akka-docs/rst/java/fault-tolerance.rst b/akka-docs/rst/java/fault-tolerance.rst index 9cb9d234fd..74b5a0cb5f 100644 --- a/akka-docs/rst/java/fault-tolerance.rst +++ b/akka-docs/rst/java/fault-tolerance.rst @@ -24,6 +24,13 @@ sample as it is easy to follow the log output to understand what is happening in fault-tolerance-sample +.. note:: + + If the strategy is declared inside the supervising actor (as opposed to + as a static property or class) its decider has access to all internal state of + the actor in a thread-safe fashion, including obtaining a reference to the + currently failed child (available as the ``getSender()`` of the failure message). + Creating a Supervisor Strategy ------------------------------ diff --git a/akka-docs/rst/java/untyped-actors.rst b/akka-docs/rst/java/untyped-actors.rst index 62ea154daa..ab01e31216 100644 --- a/akka-docs/rst/java/untyped-actors.rst +++ b/akka-docs/rst/java/untyped-actors.rst @@ -136,8 +136,20 @@ to have them converted into actual Debug messages). 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 + + This strategy is typically declared inside the actor in order to have access + to the actor’s internal state within the decider function: since failure is + communicated as a message sent to the supervisor and processed like other + messages (albeit outside of the normal behavior), all values and variables + within the actor are available, as is the ``getSender()`` reference (which will + be the immediate child reporting the failure; if the original failure + occurred within a distant descendant it is still reported one level up at a + time). + * :obj:`getContext()` exposes contextual information for the actor and the current message, such as: * factory methods to create child actors (:meth:`actorOf`) @@ -212,16 +224,21 @@ mentioned above: which caused the restart and the message which triggered that exception; the latter may be ``None`` if the restart was not caused by processing a message, e.g. when a supervisor does not trap the exception and is restarted - in turn by its supervisor. This method is the best place for cleaning up, - preparing hand-over to the fresh actor instance, etc. - By default it stops all children and calls :meth:`postStop`. + in turn by its supervisor, or if an actor is restarted due to a sibling’s + failure. If the message is available, then that message’s sender is also + accessible in the usual way (i.e. by calling ``getSender()``). + + This method is the best place for cleaning up, preparing hand-over to the + fresh actor instance, etc. By default it stops all children and calls + :meth:`postStop`. + 2. The initial factory from the ``actorOf`` call is used to produce the fresh instance. + 3. The new actor’s :meth:`postRestart` method is invoked with the exception which caused the restart. By default the :meth:`preStart` is called, just as in the normal start-up case. - An actor restart replaces only the actual actor object; the contents of the mailbox is unaffected by the restart, so processing of messages will resume after the :meth:`postRestart` hook returns. The message @@ -660,29 +677,29 @@ kind of exception is thrown, e.g. a database exception. What happens to the Message --------------------------- -If an exception is thrown while a message is being processed (so taken of his -mailbox and handed over to the receive), then this message will be lost. It is -important to understand that it is not put back on the mailbox. So if you want -to retry processing of a message, you need to deal with it yourself by catching -the exception and retry your flow. Make sure that you put a bound on the number -of retries since you don't want a system to livelock (so consuming a lot of cpu -cycles without making progress). +If an exception is thrown while a message is being processed (i.e. taken out of +its mailbox and handed over to the current behavior), then this message will be +lost. It is important to understand that it is not put back on the mailbox. So +if you want to retry processing of a message, you need to deal with it yourself +by catching the exception and retry your flow. Make sure that you put a bound +on the number of retries since you don't want a system to livelock (so +consuming a lot of cpu cycles without making progress). Another possibility +would be to have a look at the :ref:`PeekMailbox pattern `. What happens to the mailbox --------------------------- If an exception is thrown while a message is being processed, nothing happens to the mailbox. If the actor is restarted, the same mailbox will be there. So all -messages on that mailbox, will be there as well. +messages on that mailbox will be there as well. What happens to the actor ------------------------- -If an exception is thrown, the actor instance is discarded and a new instance is -created. This new instance will now be used in the actor references to this actor -(so this is done invisible to the developer). Note that this means that current -state of the failing actor instance is lost if you don't store and restore it in -``preRestart`` and ``postRestart`` callbacks. +If code within an actor throws an exception, that actor is suspended and the +supervision process is started (see :ref:`supervision`). Depending on the +supervisor’s decision the actor is resumed (as if nothing happened), restarted +(wiping out its internal state and starting from scratch) or terminated. Initialization patterns ======================= diff --git a/akka-docs/rst/scala/actors.rst b/akka-docs/rst/scala/actors.rst index a6807789c8..723f4b4669 100644 --- a/akka-docs/rst/scala/actors.rst +++ b/akka-docs/rst/scala/actors.rst @@ -240,8 +240,20 @@ actual Debug messages). 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 + + This strategy is typically declared inside the actor in order to have access + to the actor’s internal state within the decider function: since failure is + communicated as a message sent to the supervisor and processed like other + messages (albeit outside of the normal behavior), all values and variables + within the actor are available, as is the ``sender`` reference (which will + be the immediate child reporting the failure; if the original failure + occurred within a distant descendant it is still reported one level up at a + time). + * :obj:`context` exposes contextual information for the actor and the current message, such as: * factory methods to create child actors (:meth:`actorOf`) @@ -324,16 +336,21 @@ mentioned above: which caused the restart and the message which triggered that exception; the latter may be ``None`` if the restart was not caused by processing a message, e.g. when a supervisor does not trap the exception and is restarted - in turn by its supervisor. This method is the best place for cleaning up, - preparing hand-over to the fresh actor instance, etc. - By default it stops all children and calls :meth:`postStop`. + in turn by its supervisor, or if an actor is restarted due to a sibling’s + failure. If the message is available, then that message’s sender is also + accessible in the usual way (i.e. by calling ``sender``). + + This method is the best place for cleaning up, preparing hand-over to the + fresh actor instance, etc. By default it stops all children and calls + :meth:`postStop`. + 2. The initial factory from the ``actorOf`` call is used to produce the fresh instance. + 3. The new actor’s :meth:`postRestart` method is invoked with the exception which caused the restart. By default the :meth:`preStart` is called, just as in the normal start-up case. - An actor restart replaces only the actual actor object; the contents of the mailbox is unaffected by the restart, so processing of messages will resume after the :meth:`postRestart` hook returns. The message @@ -788,29 +805,29 @@ kind of exception is thrown, e.g. a database exception. What happens to the Message --------------------------- -If an exception is thrown while a message is being processed (so taken of his -mailbox and handed over to the receive), then this message will be lost. It is -important to understand that it is not put back on the mailbox. So if you want -to retry processing of a message, you need to deal with it yourself by catching -the exception and retry your flow. Make sure that you put a bound on the number -of retries since you don't want a system to livelock (so consuming a lot of cpu -cycles without making progress). +If an exception is thrown while a message is being processed (i.e. taken out of +its mailbox and handed over to the current behavior), then this message will be +lost. It is important to understand that it is not put back on the mailbox. So +if you want to retry processing of a message, you need to deal with it yourself +by catching the exception and retry your flow. Make sure that you put a bound +on the number of retries since you don't want a system to livelock (so +consuming a lot of cpu cycles without making progress). Another possibility +would be to have a look at the :ref:`PeekMailbox pattern `. What happens to the mailbox --------------------------- If an exception is thrown while a message is being processed, nothing happens to the mailbox. If the actor is restarted, the same mailbox will be there. So all -messages on that mailbox, will be there as well. +messages on that mailbox will be there as well. What happens to the actor ------------------------- -If an exception is thrown, the actor instance is discarded and a new instance is -created. This new instance will now be used in the actor references to this actor -(so this is done invisible to the developer). Note that this means that current -state of the failing actor instance is lost if you don't store and restore it in -``preRestart`` and ``postRestart`` callbacks. +If code within an actor throws an exception, that actor is suspended and the +supervision process is started (see :ref:`supervision`). Depending on the +supervisor’s decision the actor is resumed (as if nothing happened), restarted +(wiping out its internal state and starting from scratch) or terminated. Extending Actors using PartialFunction chaining diff --git a/akka-docs/rst/scala/fault-tolerance.rst b/akka-docs/rst/scala/fault-tolerance.rst index 6b6559e647..9a2d36fbe1 100644 --- a/akka-docs/rst/scala/fault-tolerance.rst +++ b/akka-docs/rst/scala/fault-tolerance.rst @@ -49,6 +49,13 @@ The match statement which forms the bulk of the body is of type ``Decider``, which is a ``PartialFunction[Throwable, Directive]``. This is the piece which maps child failure types to their corresponding directives. +.. note:: + + If the strategy is declared inside the supervising actor (as opposed to + within a companion object) its decider has access to all internal state of + the actor in a thread-safe fashion, including obtaining a reference to the + currently failed child (available as the ``sender`` of the failure message). + Default Supervisor Strategy ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/akka-docs/rst/scala/io.rst b/akka-docs/rst/scala/io.rst index 607cbca399..6d9b5f259a 100644 --- a/akka-docs/rst/scala/io.rst +++ b/akka-docs/rst/scala/io.rst @@ -427,3 +427,14 @@ Architecture in-depth For further details on the design and internal architecture see :ref:`io-layer`. .. _spray.io: http://spray.io + +Link to the old IO documentation +-------------------------------- + +.. This is only in here to avoid a warning about io-old not being part of any toctree. + +.. toctree:: + :maxdepth: 1 + + io-old +