Merge pull request #1186 from akka/wip-2509-sender-preRestart-∂π
clarify `sender` in preRestart, see #2509
This commit is contained in:
commit
fc180cde22
6 changed files with 109 additions and 34 deletions
|
|
@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ sample as it is easy to follow the log output to understand what is happening in
|
||||||
|
|
||||||
fault-tolerance-sample
|
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
|
Creating a Supervisor Strategy
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,20 @@ to have them converted into actual Debug messages).
|
||||||
In addition, it offers:
|
In addition, it offers:
|
||||||
|
|
||||||
* :obj:`getSelf()` reference to the :class:`ActorRef` of the actor
|
* :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:`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:`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:
|
* :obj:`getContext()` exposes contextual information for the actor and the current message, such as:
|
||||||
|
|
||||||
* factory methods to create child actors (:meth:`actorOf`)
|
* 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
|
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
|
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
|
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,
|
in turn by its supervisor, or if an actor is restarted due to a sibling’s
|
||||||
preparing hand-over to the fresh actor instance, etc.
|
failure. If the message is available, then that message’s sender is also
|
||||||
By default it stops all children and calls :meth:`postStop`.
|
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
|
2. The initial factory from the ``actorOf`` call is used
|
||||||
to produce the fresh instance.
|
to produce the fresh instance.
|
||||||
|
|
||||||
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
||||||
which caused the restart. By default the :meth:`preStart`
|
which caused the restart. By default the :meth:`preStart`
|
||||||
is called, just as in the normal start-up case.
|
is called, just as in the normal start-up case.
|
||||||
|
|
||||||
|
|
||||||
An actor restart replaces only the actual actor object; the contents of the
|
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
|
mailbox is unaffected by the restart, so processing of messages will resume
|
||||||
after the :meth:`postRestart` hook returns. The message
|
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
|
What happens to the Message
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
If an exception is thrown while a message is being processed (so taken of his
|
If an exception is thrown while a message is being processed (i.e. taken out of
|
||||||
mailbox and handed over to the receive), then this message will be lost. It is
|
its mailbox and handed over to the current behavior), then this message will be
|
||||||
important to understand that it is not put back on the mailbox. So if you want
|
lost. It is important to understand that it is not put back on the mailbox. So
|
||||||
to retry processing of a message, you need to deal with it yourself by catching
|
if you want to retry processing of a message, you need to deal with it yourself
|
||||||
the exception and retry your flow. Make sure that you put a bound on the number
|
by catching the exception and retry your flow. Make sure that you put a bound
|
||||||
of retries since you don't want a system to livelock (so consuming a lot of cpu
|
on the number of retries since you don't want a system to livelock (so
|
||||||
cycles without making progress).
|
consuming a lot of cpu cycles without making progress). Another possibility
|
||||||
|
would be to have a look at the :ref:`PeekMailbox pattern <mailbox-acking>`.
|
||||||
|
|
||||||
What happens to the mailbox
|
What happens to the mailbox
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
If an exception is thrown while a message is being processed, nothing happens to
|
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
|
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
|
What happens to the actor
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
If an exception is thrown, the actor instance is discarded and a new instance is
|
If code within an actor throws an exception, that actor is suspended and the
|
||||||
created. This new instance will now be used in the actor references to this actor
|
supervision process is started (see :ref:`supervision`). Depending on the
|
||||||
(so this is done invisible to the developer). Note that this means that current
|
supervisor’s decision the actor is resumed (as if nothing happened), restarted
|
||||||
state of the failing actor instance is lost if you don't store and restore it in
|
(wiping out its internal state and starting from scratch) or terminated.
|
||||||
``preRestart`` and ``postRestart`` callbacks.
|
|
||||||
|
|
||||||
Initialization patterns
|
Initialization patterns
|
||||||
=======================
|
=======================
|
||||||
|
|
|
||||||
|
|
@ -240,8 +240,20 @@ actual Debug messages).
|
||||||
In addition, it offers:
|
In addition, it offers:
|
||||||
|
|
||||||
* :obj:`self` reference to the :class:`ActorRef` of the actor
|
* :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:`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:`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:
|
* :obj:`context` exposes contextual information for the actor and the current message, such as:
|
||||||
|
|
||||||
* factory methods to create child actors (:meth:`actorOf`)
|
* 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
|
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
|
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
|
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,
|
in turn by its supervisor, or if an actor is restarted due to a sibling’s
|
||||||
preparing hand-over to the fresh actor instance, etc.
|
failure. If the message is available, then that message’s sender is also
|
||||||
By default it stops all children and calls :meth:`postStop`.
|
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
|
2. The initial factory from the ``actorOf`` call is used
|
||||||
to produce the fresh instance.
|
to produce the fresh instance.
|
||||||
|
|
||||||
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
||||||
which caused the restart. By default the :meth:`preStart`
|
which caused the restart. By default the :meth:`preStart`
|
||||||
is called, just as in the normal start-up case.
|
is called, just as in the normal start-up case.
|
||||||
|
|
||||||
|
|
||||||
An actor restart replaces only the actual actor object; the contents of the
|
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
|
mailbox is unaffected by the restart, so processing of messages will resume
|
||||||
after the :meth:`postRestart` hook returns. The message
|
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
|
What happens to the Message
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
If an exception is thrown while a message is being processed (so taken of his
|
If an exception is thrown while a message is being processed (i.e. taken out of
|
||||||
mailbox and handed over to the receive), then this message will be lost. It is
|
its mailbox and handed over to the current behavior), then this message will be
|
||||||
important to understand that it is not put back on the mailbox. So if you want
|
lost. It is important to understand that it is not put back on the mailbox. So
|
||||||
to retry processing of a message, you need to deal with it yourself by catching
|
if you want to retry processing of a message, you need to deal with it yourself
|
||||||
the exception and retry your flow. Make sure that you put a bound on the number
|
by catching the exception and retry your flow. Make sure that you put a bound
|
||||||
of retries since you don't want a system to livelock (so consuming a lot of cpu
|
on the number of retries since you don't want a system to livelock (so
|
||||||
cycles without making progress).
|
consuming a lot of cpu cycles without making progress). Another possibility
|
||||||
|
would be to have a look at the :ref:`PeekMailbox pattern <mailbox-acking>`.
|
||||||
|
|
||||||
What happens to the mailbox
|
What happens to the mailbox
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
If an exception is thrown while a message is being processed, nothing happens to
|
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
|
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
|
What happens to the actor
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
If an exception is thrown, the actor instance is discarded and a new instance is
|
If code within an actor throws an exception, that actor is suspended and the
|
||||||
created. This new instance will now be used in the actor references to this actor
|
supervision process is started (see :ref:`supervision`). Depending on the
|
||||||
(so this is done invisible to the developer). Note that this means that current
|
supervisor’s decision the actor is resumed (as if nothing happened), restarted
|
||||||
state of the failing actor instance is lost if you don't store and restore it in
|
(wiping out its internal state and starting from scratch) or terminated.
|
||||||
``preRestart`` and ``postRestart`` callbacks.
|
|
||||||
|
|
||||||
|
|
||||||
Extending Actors using PartialFunction chaining
|
Extending Actors using PartialFunction chaining
|
||||||
|
|
|
||||||
|
|
@ -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
|
which is a ``PartialFunction[Throwable, Directive]``. This
|
||||||
is the piece which maps child failure types to their corresponding directives.
|
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
|
Default Supervisor Strategy
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -427,3 +427,14 @@ Architecture in-depth
|
||||||
For further details on the design and internal architecture see :ref:`io-layer`.
|
For further details on the design and internal architecture see :ref:`io-layer`.
|
||||||
|
|
||||||
.. _spray.io: http://spray.io
|
.. _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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue