Split mailbox documentation into a separate section. See #3341
This commit is contained in:
parent
beed693c1b
commit
6abec367f2
10 changed files with 330 additions and 326 deletions
|
|
@ -141,159 +141,3 @@ Note that it's not guaranteed that the *same* thread is used over time, since th
|
||||||
is used for ``PinnedDispatcher`` to keep resource usage down in case of idle actors. To use the same
|
is used for ``PinnedDispatcher`` to keep resource usage down in case of idle actors. To use the same
|
||||||
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
|
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
|
||||||
configuration of the ``PinnedDispatcher``.
|
configuration of the ``PinnedDispatcher``.
|
||||||
|
|
||||||
Mailboxes
|
|
||||||
---------
|
|
||||||
|
|
||||||
An Akka ``Mailbox`` holds the messages that are destined for an ``Actor``.
|
|
||||||
Normally each ``Actor`` has its own mailbox, but with example a ``BalancingDispatcher`` all actors with the same ``BalancingDispatcher`` will share a single instance.
|
|
||||||
|
|
||||||
Builtin implementations
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Akka comes shipped with a number of default mailbox implementations:
|
|
||||||
|
|
||||||
* UnboundedMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.ConcurrentLinkedQueue``
|
|
||||||
|
|
||||||
- Blocking: No
|
|
||||||
|
|
||||||
- Bounded: No
|
|
||||||
|
|
||||||
* BoundedMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.LinkedBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: Yes
|
|
||||||
|
|
||||||
* UnboundedPriorityMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.PriorityBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: No
|
|
||||||
|
|
||||||
* BoundedPriorityMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.PriorityBlockingQueue`` wrapped in an ``akka.util.BoundedBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: Yes
|
|
||||||
|
|
||||||
* Durable mailboxes, see :ref:`durable-mailboxes-java`.
|
|
||||||
|
|
||||||
Mailbox configuration examples
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
How to create a PriorityMailbox:
|
|
||||||
|
|
||||||
.. includecode:: ../java/code/docs/dispatcher/DispatcherDocTest.java#prio-mailbox
|
|
||||||
|
|
||||||
And then add it to the configuration:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher-config
|
|
||||||
|
|
||||||
And then an example on how you would use it:
|
|
||||||
|
|
||||||
.. includecode:: ../java/code/docs/dispatcher/DispatcherDocTest.java#prio-dispatcher
|
|
||||||
|
|
||||||
It is also possible to configure a mailbox type directly like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
|
||||||
:include: prio-mailbox-config-java,mailbox-deployment-config
|
|
||||||
|
|
||||||
And then use it either from deployment like this:
|
|
||||||
|
|
||||||
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#defining-mailbox-in-config
|
|
||||||
|
|
||||||
Or code like this:
|
|
||||||
|
|
||||||
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#defining-mailbox-in-code
|
|
||||||
|
|
||||||
|
|
||||||
Requiring a message queue type for an Actor
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
It is possible to require a certain type of message queue for a certain type of actor
|
|
||||||
by having that actor implement the parameterized interface :class:`RequiresMessageQueue`. Here is
|
|
||||||
an example:
|
|
||||||
|
|
||||||
.. includecode:: code/docs/actor/MyBoundedUntypedActor.java#my-bounded-untyped-actor
|
|
||||||
|
|
||||||
The type parameter to the :class:`RequiresMessageQueue` interface needs to be mapped to a mailbox in
|
|
||||||
configuration like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
|
||||||
:include: bounded-mailbox-config,required-mailbox-config
|
|
||||||
|
|
||||||
Now every time you create an actor of type :class:`MyBoundedUntypedActor` it will try to get a bounded
|
|
||||||
mailbox. If the actor has a different mailbox configured in deployment, either directly or via
|
|
||||||
a dispatcher with a specified mailbox type, then that will override this mapping.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
|
||||||
interface and if the queue doesn't implement the required type then actor creation will fail.
|
|
||||||
|
|
||||||
|
|
||||||
Mailbox configuration precedence
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The order of precedence for the mailbox type of an actor, where lower numbers override higher, is:
|
|
||||||
|
|
||||||
1. Mailbox type configured in the deployment of the actor
|
|
||||||
2. Mailbox type configured on the dispatcher of the actor
|
|
||||||
3. Mailbox type configured on the Props of the actor
|
|
||||||
4. Mailbox type configured via message queue requirement
|
|
||||||
|
|
||||||
|
|
||||||
Creating your own Mailbox type
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
An example is worth a thousand quacks:
|
|
||||||
|
|
||||||
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#imports-custom
|
|
||||||
|
|
||||||
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#mailbox-implementation-example
|
|
||||||
|
|
||||||
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
|
||||||
configuration, or the mailbox configuration.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Make sure to include a constructor which takes
|
|
||||||
``akka.actor.ActorSystem.Settings`` and ``com.typesafe.config.Config``
|
|
||||||
arguments, as this constructor is invoked reflectively to construct your
|
|
||||||
mailbox type. The config passed in as second argument is that section from
|
|
||||||
the configuration which describes the dispatcher or mailbox setting using
|
|
||||||
this mailbox type; the mailbox type will be instantiated once for each
|
|
||||||
dispatcher or mailbox setting using it.
|
|
||||||
|
|
||||||
|
|
||||||
Special Semantics of ``system.actorOf``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
In order to make ``system.actorOf`` both synchronous and non-blocking while
|
|
||||||
keeping the return type :class:`ActorRef` (and the semantics that the returned
|
|
||||||
ref is fully functional), special handling takes place for this case. Behind
|
|
||||||
the scenes, a hollow kind of actor reference is constructed, which is sent to
|
|
||||||
the system’s guardian actor who actually creates the actor and its context and
|
|
||||||
puts those inside the reference. Until that has happened, messages sent to the
|
|
||||||
:class:`ActorRef` will be queued locally, and only upon swapping the real
|
|
||||||
filling in will they be transferred into the real mailbox. Thus,
|
|
||||||
|
|
||||||
.. code-block:: scala
|
|
||||||
|
|
||||||
final Props props = ...
|
|
||||||
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
|
||||||
system.actorOf(props.withDispatcher("myCustomMailbox").tell("bang", sender);
|
|
||||||
assert(MyCustomMailbox.getInstance().getLastEnqueued().equals("bang"));
|
|
||||||
|
|
||||||
will probably fail; you will have to allow for some time to pass and retry the
|
|
||||||
check à la :meth:`TestKit.awaitCond`.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ mailbox when the node of the actor resides on crashes, then when you restart the
|
||||||
node, the actor will be able to continue processing as if nothing had happened;
|
node, the actor will be able to continue processing as if nothing had happened;
|
||||||
with all pending messages still in its mailbox.
|
with all pending messages still in its mailbox.
|
||||||
|
|
||||||
You configure durable mailboxes through the dispatcher. The actor is oblivious
|
You configure durable mailboxes through the dispatcher or the actor deployment (see
|
||||||
to which type of mailbox it is using.
|
:ref:`mailboxes-java`). The actor is oblivious to which type of mailbox it is using.
|
||||||
|
|
||||||
This gives you an excellent way of creating bulkheads in your application, where
|
This gives you an excellent way of creating bulkheads in your application, where
|
||||||
groups of actors sharing the same dispatcher also share the same backing
|
groups of actors sharing the same dispatcher also share the same backing
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Actors
|
||||||
typed-actors
|
typed-actors
|
||||||
fault-tolerance
|
fault-tolerance
|
||||||
dispatchers
|
dispatchers
|
||||||
|
mailboxes
|
||||||
routing
|
routing
|
||||||
fsm
|
fsm
|
||||||
testing
|
testing
|
||||||
|
|
|
||||||
158
akka-docs/rst/java/mailboxes.rst
Normal file
158
akka-docs/rst/java/mailboxes.rst
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
.. _mailboxes-java:
|
||||||
|
|
||||||
|
Mailboxes
|
||||||
|
=========
|
||||||
|
|
||||||
|
An Akka ``Mailbox`` holds the messages that are destined for an ``Actor``.
|
||||||
|
Normally each ``Actor`` has its own mailbox, but with for example a ``BalancingDispatcher``
|
||||||
|
all actors with the same ``BalancingDispatcher`` will share a single instance.
|
||||||
|
|
||||||
|
Builtin Mailbox Implementations
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Akka comes shipped with a number of default mailbox implementations:
|
||||||
|
|
||||||
|
* UnboundedMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.ConcurrentLinkedQueue``
|
||||||
|
|
||||||
|
- Blocking: No
|
||||||
|
|
||||||
|
- Bounded: No
|
||||||
|
|
||||||
|
* BoundedMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.LinkedBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: Yes
|
||||||
|
|
||||||
|
* UnboundedPriorityMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.PriorityBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: No
|
||||||
|
|
||||||
|
* BoundedPriorityMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.PriorityBlockingQueue`` wrapped in an ``akka.util.BoundedBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: Yes
|
||||||
|
|
||||||
|
* Durable mailboxes, see :ref:`durable-mailboxes-java`.
|
||||||
|
|
||||||
|
Mailbox configuration examples
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
How to create a PriorityMailbox:
|
||||||
|
|
||||||
|
.. includecode:: ../java/code/docs/dispatcher/DispatcherDocTest.java#prio-mailbox
|
||||||
|
|
||||||
|
And then add it to the configuration:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher-config
|
||||||
|
|
||||||
|
And then an example on how you would use it:
|
||||||
|
|
||||||
|
.. includecode:: ../java/code/docs/dispatcher/DispatcherDocTest.java#prio-dispatcher
|
||||||
|
|
||||||
|
It is also possible to configure a mailbox type directly like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
||||||
|
:include: prio-mailbox-config-java,mailbox-deployment-config
|
||||||
|
|
||||||
|
And then use it either from deployment like this:
|
||||||
|
|
||||||
|
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#defining-mailbox-in-config
|
||||||
|
|
||||||
|
Or code like this:
|
||||||
|
|
||||||
|
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#defining-mailbox-in-code
|
||||||
|
|
||||||
|
|
||||||
|
Requiring a message queue type for an Actor
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
It is possible to require a certain type of message queue for a certain type of actor
|
||||||
|
by having that actor implement the parameterized interface :class:`RequiresMessageQueue`. Here is
|
||||||
|
an example:
|
||||||
|
|
||||||
|
.. includecode:: code/docs/actor/MyBoundedUntypedActor.java#my-bounded-untyped-actor
|
||||||
|
|
||||||
|
The type parameter to the :class:`RequiresMessageQueue` interface needs to be mapped to a mailbox in
|
||||||
|
configuration like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
||||||
|
:include: bounded-mailbox-config,required-mailbox-config
|
||||||
|
|
||||||
|
Now every time you create an actor of type :class:`MyBoundedUntypedActor` it will try to get a bounded
|
||||||
|
mailbox. If the actor has a different mailbox configured in deployment, either directly or via
|
||||||
|
a dispatcher with a specified mailbox type, then that will override this mapping.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
||||||
|
interface and if the queue doesn't implement the required type then actor creation will fail.
|
||||||
|
|
||||||
|
|
||||||
|
Mailbox configuration precedence
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
The order of precedence for the mailbox type of an actor, where lower numbers override higher, is:
|
||||||
|
|
||||||
|
1. Mailbox type configured in the deployment of the actor
|
||||||
|
2. Mailbox type configured on the dispatcher of the actor
|
||||||
|
3. Mailbox type configured on the Props of the actor
|
||||||
|
4. Mailbox type configured via message queue requirement
|
||||||
|
|
||||||
|
|
||||||
|
Creating your own Mailbox type
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
An example is worth a thousand quacks:
|
||||||
|
|
||||||
|
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#imports-custom
|
||||||
|
|
||||||
|
.. includecode:: code/docs/dispatcher/DispatcherDocTest.java#mailbox-implementation-example
|
||||||
|
|
||||||
|
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
||||||
|
configuration, or the mailbox configuration.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Make sure to include a constructor which takes
|
||||||
|
``akka.actor.ActorSystem.Settings`` and ``com.typesafe.config.Config``
|
||||||
|
arguments, as this constructor is invoked reflectively to construct your
|
||||||
|
mailbox type. The config passed in as second argument is that section from
|
||||||
|
the configuration which describes the dispatcher or mailbox setting using
|
||||||
|
this mailbox type; the mailbox type will be instantiated once for each
|
||||||
|
dispatcher or mailbox setting using it.
|
||||||
|
|
||||||
|
|
||||||
|
Special Semantics of ``system.actorOf``
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
In order to make ``system.actorOf`` both synchronous and non-blocking while
|
||||||
|
keeping the return type :class:`ActorRef` (and the semantics that the returned
|
||||||
|
ref is fully functional), special handling takes place for this case. Behind
|
||||||
|
the scenes, a hollow kind of actor reference is constructed, which is sent to
|
||||||
|
the system’s guardian actor who actually creates the actor and its context and
|
||||||
|
puts those inside the reference. Until that has happened, messages sent to the
|
||||||
|
:class:`ActorRef` will be queued locally, and only upon swapping the real
|
||||||
|
filling in will they be transferred into the real mailbox. Thus,
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
final Props props = ...
|
||||||
|
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
||||||
|
system.actorOf(props.withDispatcher("myCustomMailbox").tell("bang", sender);
|
||||||
|
assert(MyCustomMailbox.getInstance().getLastEnqueued().equals("bang"));
|
||||||
|
|
||||||
|
will probably fail; you will have to allow for some time to pass and retry the
|
||||||
|
check à la :meth:`TestKit.awaitCond`.
|
||||||
|
|
||||||
|
|
@ -149,10 +149,12 @@ Creating Actors with Factory Methods
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
If your UntypedActor has a constructor that takes parameters then those need to
|
If your UntypedActor has a constructor that takes parameters then those need to
|
||||||
be part of the :class:`Props` as well, as described `above <Props>`_. But there
|
be part of the :class:`Props` as well, as described `above`__. But there
|
||||||
are cases when a factory method must be used, for example when the actual
|
are cases when a factory method must be used, for example when the actual
|
||||||
constructor arguments are determined by a dependency injection framework.
|
constructor arguments are determined by a dependency injection framework.
|
||||||
|
|
||||||
|
__ Props_
|
||||||
|
|
||||||
.. includecode:: code/docs/actor/UntypedActorDocTest.java#import-indirect
|
.. includecode:: code/docs/actor/UntypedActorDocTest.java#import-indirect
|
||||||
.. includecode:: code/docs/actor/UntypedActorDocTest.java
|
.. includecode:: code/docs/actor/UntypedActorDocTest.java
|
||||||
:include: creating-indirectly
|
:include: creating-indirectly
|
||||||
|
|
@ -691,14 +693,8 @@ behavior. Upon changing the actor's message handler, i.e., right
|
||||||
before invoking ``getContext().become()`` or ``getContext().unbecome()``, all
|
before invoking ``getContext().become()`` or ``getContext().unbecome()``, all
|
||||||
stashed messages can be "unstashed", thereby prepending them to the actor's
|
stashed messages can be "unstashed", thereby prepending them to the actor's
|
||||||
mailbox. This way, the stashed messages can be processed in the same
|
mailbox. This way, the stashed messages can be processed in the same
|
||||||
order as they have been received originally.
|
order as they have been received originally. An actor that extends
|
||||||
|
``UntypedActorWithStash`` will automatically get a deque-based mailbox.
|
||||||
.. warning::
|
|
||||||
|
|
||||||
Please note that the stash can only be used together with actors
|
|
||||||
that have a deque-based mailbox. For this, configure the
|
|
||||||
``mailbox-type`` of the dispatcher to be a deque-based mailbox, such as
|
|
||||||
``akka.dispatch.UnboundedDequeBasedMailbox`` (see :ref:`dispatchers-java`).
|
|
||||||
|
|
||||||
Here is an example of the ``UntypedActorWithStash`` class in action:
|
Here is an example of the ``UntypedActorWithStash`` class in action:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,10 +165,12 @@ Creating Actors with Factory Methods
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
If your UntypedActor has a constructor that takes parameters then those need to
|
If your UntypedActor has a constructor that takes parameters then those need to
|
||||||
be part of the :class:`Props` as well, as described `above <Props>`_. But there
|
be part of the :class:`Props` as well, as described `above`__. But there
|
||||||
are cases when a factory method must be used, for example when the actual
|
are cases when a factory method must be used, for example when the actual
|
||||||
constructor arguments are determined by a dependency injection framework.
|
constructor arguments are determined by a dependency injection framework.
|
||||||
|
|
||||||
|
__ Props_
|
||||||
|
|
||||||
.. includecode:: code/docs/actor/ActorDocSpec.scala
|
.. includecode:: code/docs/actor/ActorDocSpec.scala
|
||||||
:include: creating-indirectly
|
:include: creating-indirectly
|
||||||
:exclude: obtain-fresh-Actor-instance-from-DI-framework
|
:exclude: obtain-fresh-Actor-instance-from-DI-framework
|
||||||
|
|
@ -795,8 +797,9 @@ order as they have been received originally.
|
||||||
|
|
||||||
Please note that the ``Stash`` can only be used together with actors
|
Please note that the ``Stash`` can only be used together with actors
|
||||||
that have a deque-based mailbox. For this, configure the
|
that have a deque-based mailbox. For this, configure the
|
||||||
``mailbox-type`` of the dispatcher to be a deque-based mailbox, such as
|
``mailbox-type`` of the dispatcher or in the deployment of the actor
|
||||||
``akka.dispatch.UnboundedDequeBasedMailbox`` (see :ref:`dispatchers-scala`).
|
to be a deque-based mailbox, such as ``akka.dispatch.UnboundedDequeBasedMailbox``
|
||||||
|
(see :ref:`mailboxes-scala`).
|
||||||
|
|
||||||
Here is an example of the ``Stash`` in action:
|
Here is an example of the ``Stash`` in action:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,157 +143,3 @@ Note that it's not guaranteed that the *same* thread is used over time, since th
|
||||||
is used for ``PinnedDispatcher`` to keep resource usage down in case of idle actors. To use the same
|
is used for ``PinnedDispatcher`` to keep resource usage down in case of idle actors. To use the same
|
||||||
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
|
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
|
||||||
configuration of the ``PinnedDispatcher``.
|
configuration of the ``PinnedDispatcher``.
|
||||||
|
|
||||||
Mailboxes
|
|
||||||
---------
|
|
||||||
|
|
||||||
An Akka ``Mailbox`` holds the messages that are destined for an ``Actor``.
|
|
||||||
Normally each ``Actor`` has its own mailbox, but with example a ``BalancingDispatcher`` all actors with the same ``BalancingDispatcher`` will share a single instance.
|
|
||||||
|
|
||||||
Builtin implementations
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Akka comes shipped with a number of default mailbox implementations:
|
|
||||||
|
|
||||||
* UnboundedMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.ConcurrentLinkedQueue``
|
|
||||||
|
|
||||||
- Blocking: No
|
|
||||||
|
|
||||||
- Bounded: No
|
|
||||||
|
|
||||||
* BoundedMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.LinkedBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: Yes
|
|
||||||
|
|
||||||
* UnboundedPriorityMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.concurrent.PriorityBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: No
|
|
||||||
|
|
||||||
* BoundedPriorityMailbox
|
|
||||||
|
|
||||||
- Backed by a ``java.util.PriorityBlockingQueue`` wrapped in an ``akka.util.BoundedBlockingQueue``
|
|
||||||
|
|
||||||
- Blocking: Yes
|
|
||||||
|
|
||||||
- Bounded: Yes
|
|
||||||
|
|
||||||
* Durable mailboxes, see :ref:`durable-mailboxes-scala`.
|
|
||||||
|
|
||||||
Mailbox configuration examples
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
How to create a PriorityMailbox:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-mailbox
|
|
||||||
|
|
||||||
And then add it to the configuration:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher-config
|
|
||||||
|
|
||||||
And then an example on how you would use it:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher
|
|
||||||
|
|
||||||
It is also possible to configure a mailbox type directly like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
|
||||||
:include: prio-mailbox-config,mailbox-deployment-config
|
|
||||||
|
|
||||||
And then use it either from deployment like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#defining-mailbox-in-config
|
|
||||||
|
|
||||||
Or code like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#defining-mailbox-in-code
|
|
||||||
|
|
||||||
|
|
||||||
Requiring a message queue type for an Actor
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
It is possible to require a certain type of message queue for a certain type of actor
|
|
||||||
by having that actor extend the parameterized trait :class:`RequiresMessageQueue`. Here is
|
|
||||||
an example:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#required-mailbox-class
|
|
||||||
|
|
||||||
The type parameter to the :class:`RequiresMessageQueue` trait needs to be mapped to a mailbox in
|
|
||||||
configuration like this:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
|
||||||
:include: bounded-mailbox-config,required-mailbox-config
|
|
||||||
|
|
||||||
Now every time you create an actor of type :class:`MyBoundedActor` it will try to get a bounded
|
|
||||||
mailbox. If the actor has a different mailbox configured in deployment, either directly or via
|
|
||||||
a dispatcher with a specified mailbox type, then that will override this mapping.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
|
||||||
trait and if the queue doesn't implement the required type then actor creation will fail.
|
|
||||||
|
|
||||||
|
|
||||||
Mailbox configuration precedence
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The order of precedence for the mailbox type of an actor, where lower numbers override higher, is:
|
|
||||||
|
|
||||||
1. Mailbox type configured in the deployment of the actor
|
|
||||||
2. Mailbox type configured on the dispatcher of the actor
|
|
||||||
3. Mailbox type configured on the Props of the actor
|
|
||||||
4. Mailbox type configured via message queue requirement
|
|
||||||
|
|
||||||
|
|
||||||
Creating your own Mailbox type
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
An example is worth a thousand quacks:
|
|
||||||
|
|
||||||
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#mailbox-implementation-example
|
|
||||||
|
|
||||||
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
|
||||||
configuration, or the mailbox configuration.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Make sure to include a constructor which takes
|
|
||||||
``akka.actor.ActorSystem.Settings`` and ``com.typesafe.config.Config``
|
|
||||||
arguments, as this constructor is invoked reflectively to construct your
|
|
||||||
mailbox type. The config passed in as second argument is that section from
|
|
||||||
the configuration which describes the dispatcher or mailbox setting using
|
|
||||||
this mailbox type; the mailbox type will be instantiated once for each
|
|
||||||
dispatcher or mailbox setting using it.
|
|
||||||
|
|
||||||
|
|
||||||
Special Semantics of ``system.actorOf``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
In order to make ``system.actorOf`` both synchronous and non-blocking while
|
|
||||||
keeping the return type :class:`ActorRef` (and the semantics that the returned
|
|
||||||
ref is fully functional), special handling takes place for this case. Behind
|
|
||||||
the scenes, a hollow kind of actor reference is constructed, which is sent to
|
|
||||||
the system’s guardian actor who actually creates the actor and its context and
|
|
||||||
puts those inside the reference. Until that has happened, messages sent to the
|
|
||||||
:class:`ActorRef` will be queued locally, and only upon swapping the real
|
|
||||||
filling in will they be transferred into the real mailbox. Thus,
|
|
||||||
|
|
||||||
.. code-block:: scala
|
|
||||||
|
|
||||||
val props: Props = ...
|
|
||||||
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
|
||||||
system.actorOf(props.withDispatcher("myCustomMailbox")) ! "bang"
|
|
||||||
assert(MyCustomMailbox.instance.getLastEnqueuedMessage == "bang")
|
|
||||||
|
|
||||||
will probably fail; you will have to allow for some time to pass and retry the
|
|
||||||
check à la :meth:`TestKit.awaitCond`.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ mailbox when the node of the actor resides on crashes, then when you restart the
|
||||||
node, the actor will be able to continue processing as if nothing had happened;
|
node, the actor will be able to continue processing as if nothing had happened;
|
||||||
with all pending messages still in its mailbox.
|
with all pending messages still in its mailbox.
|
||||||
|
|
||||||
You configure durable mailboxes through the dispatcher. The actor is oblivious
|
You configure durable mailboxes through the dispatcher or the actor deployment (see
|
||||||
to which type of mailbox it is using.
|
:ref:`mailboxes-scala`). The actor is oblivious to which type of mailbox it is using.
|
||||||
|
|
||||||
This gives you an excellent way of creating bulkheads in your application, where
|
This gives you an excellent way of creating bulkheads in your application, where
|
||||||
groups of actors sharing the same dispatcher also share the same backing
|
groups of actors sharing the same dispatcher also share the same backing
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ Actors
|
||||||
typed-actors
|
typed-actors
|
||||||
fault-tolerance
|
fault-tolerance
|
||||||
dispatchers
|
dispatchers
|
||||||
|
mailboxes
|
||||||
routing
|
routing
|
||||||
fsm
|
fsm
|
||||||
testing
|
testing
|
||||||
|
|
|
||||||
155
akka-docs/rst/scala/mailboxes.rst
Normal file
155
akka-docs/rst/scala/mailboxes.rst
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
.. _mailboxes-scala:
|
||||||
|
|
||||||
|
Mailboxes
|
||||||
|
=========
|
||||||
|
|
||||||
|
An Akka ``Mailbox`` holds the messages that are destined for an ``Actor``.
|
||||||
|
Normally each ``Actor`` has its own mailbox, but with for example a ``BalancingDispatcher``
|
||||||
|
all actors with the same ``BalancingDispatcher`` will share a single instance.
|
||||||
|
|
||||||
|
Builtin implementations
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Akka comes shipped with a number of default mailbox implementations:
|
||||||
|
|
||||||
|
* UnboundedMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.ConcurrentLinkedQueue``
|
||||||
|
|
||||||
|
- Blocking: No
|
||||||
|
|
||||||
|
- Bounded: No
|
||||||
|
|
||||||
|
* BoundedMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.LinkedBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: Yes
|
||||||
|
|
||||||
|
* UnboundedPriorityMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.concurrent.PriorityBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: No
|
||||||
|
|
||||||
|
* BoundedPriorityMailbox
|
||||||
|
|
||||||
|
- Backed by a ``java.util.PriorityBlockingQueue`` wrapped in an ``akka.util.BoundedBlockingQueue``
|
||||||
|
|
||||||
|
- Blocking: Yes
|
||||||
|
|
||||||
|
- Bounded: Yes
|
||||||
|
|
||||||
|
* Durable mailboxes, see :ref:`durable-mailboxes-scala`.
|
||||||
|
|
||||||
|
Mailbox configuration examples
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
How to create a PriorityMailbox:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-mailbox
|
||||||
|
|
||||||
|
And then add it to the configuration:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher-config
|
||||||
|
|
||||||
|
And then an example on how you would use it:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#prio-dispatcher
|
||||||
|
|
||||||
|
It is also possible to configure a mailbox type directly like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
||||||
|
:include: prio-mailbox-config,mailbox-deployment-config
|
||||||
|
|
||||||
|
And then use it either from deployment like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#defining-mailbox-in-config
|
||||||
|
|
||||||
|
Or code like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#defining-mailbox-in-code
|
||||||
|
|
||||||
|
|
||||||
|
Requiring a message queue type for an Actor
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
It is possible to require a certain type of message queue for a certain type of actor
|
||||||
|
by having that actor extend the parameterized trait :class:`RequiresMessageQueue`. Here is
|
||||||
|
an example:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#required-mailbox-class
|
||||||
|
|
||||||
|
The type parameter to the :class:`RequiresMessageQueue` trait needs to be mapped to a mailbox in
|
||||||
|
configuration like this:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala
|
||||||
|
:include: bounded-mailbox-config,required-mailbox-config
|
||||||
|
|
||||||
|
Now every time you create an actor of type :class:`MyBoundedActor` it will try to get a bounded
|
||||||
|
mailbox. If the actor has a different mailbox configured in deployment, either directly or via
|
||||||
|
a dispatcher with a specified mailbox type, then that will override this mapping.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The type of the queue in the mailbox created for an actor will be checked against the required type in the
|
||||||
|
trait and if the queue doesn't implement the required type then actor creation will fail.
|
||||||
|
|
||||||
|
|
||||||
|
Mailbox configuration precedence
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
The order of precedence for the mailbox type of an actor, where lower numbers override higher, is:
|
||||||
|
|
||||||
|
1. Mailbox type configured in the deployment of the actor
|
||||||
|
2. Mailbox type configured on the dispatcher of the actor
|
||||||
|
3. Mailbox type configured on the Props of the actor
|
||||||
|
4. Mailbox type configured via message queue requirement
|
||||||
|
|
||||||
|
|
||||||
|
Creating your own Mailbox type
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
An example is worth a thousand quacks:
|
||||||
|
|
||||||
|
.. includecode:: ../scala/code/docs/dispatcher/DispatcherDocSpec.scala#mailbox-implementation-example
|
||||||
|
|
||||||
|
And then you just specify the FQCN of your MailboxType as the value of the "mailbox-type" in the dispatcher
|
||||||
|
configuration, or the mailbox configuration.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Make sure to include a constructor which takes
|
||||||
|
``akka.actor.ActorSystem.Settings`` and ``com.typesafe.config.Config``
|
||||||
|
arguments, as this constructor is invoked reflectively to construct your
|
||||||
|
mailbox type. The config passed in as second argument is that section from
|
||||||
|
the configuration which describes the dispatcher or mailbox setting using
|
||||||
|
this mailbox type; the mailbox type will be instantiated once for each
|
||||||
|
dispatcher or mailbox setting using it.
|
||||||
|
|
||||||
|
|
||||||
|
Special Semantics of ``system.actorOf``
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
In order to make ``system.actorOf`` both synchronous and non-blocking while
|
||||||
|
keeping the return type :class:`ActorRef` (and the semantics that the returned
|
||||||
|
ref is fully functional), special handling takes place for this case. Behind
|
||||||
|
the scenes, a hollow kind of actor reference is constructed, which is sent to
|
||||||
|
the system’s guardian actor who actually creates the actor and its context and
|
||||||
|
puts those inside the reference. Until that has happened, messages sent to the
|
||||||
|
:class:`ActorRef` will be queued locally, and only upon swapping the real
|
||||||
|
filling in will they be transferred into the real mailbox. Thus,
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
val props: Props = ...
|
||||||
|
// this actor uses MyCustomMailbox, which is assumed to be a singleton
|
||||||
|
system.actorOf(props.withDispatcher("myCustomMailbox")) ! "bang"
|
||||||
|
assert(MyCustomMailbox.instance.getLastEnqueuedMessage == "bang")
|
||||||
|
|
||||||
|
will probably fail; you will have to allow for some time to pass and retry the
|
||||||
|
check à la :meth:`TestKit.awaitCond`.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue