Split mailbox documentation into a separate section. See #3341

This commit is contained in:
Björn Antonsson 2013-05-24 15:59:53 +02:00
parent beed693c1b
commit 6abec367f2
10 changed files with 330 additions and 326 deletions

View file

@ -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
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
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 systems 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`.

View file

@ -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;
with all pending messages still in its mailbox.
You configure durable mailboxes through the dispatcher. The actor is oblivious
to which type of mailbox it is using.
You configure durable mailboxes through the dispatcher or the actor deployment (see
: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
groups of actors sharing the same dispatcher also share the same backing

View file

@ -8,6 +8,7 @@ Actors
typed-actors
fault-tolerance
dispatchers
mailboxes
routing
fsm
testing

View 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 systems 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`.

View file

@ -149,10 +149,12 @@ Creating Actors with Factory Methods
------------------------------------
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
constructor arguments are determined by a dependency injection framework.
__ Props_
.. includecode:: code/docs/actor/UntypedActorDocTest.java#import-indirect
.. includecode:: code/docs/actor/UntypedActorDocTest.java
: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
stashed messages can be "unstashed", thereby prepending them to the actor's
mailbox. This way, the stashed messages can be processed in the same
order as they have been received originally.
.. 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`).
order as they have been received originally. An actor that extends
``UntypedActorWithStash`` will automatically get a deque-based mailbox.
Here is an example of the ``UntypedActorWithStash`` class in action: