Allow different types of mailboxes on the same dispatcher. See #2687

This commit is contained in:
Björn Antonsson 2013-04-18 13:35:36 +02:00
parent c86cc0b8f7
commit c3eed374f1
32 changed files with 735 additions and 74 deletions

View file

@ -0,0 +1,14 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.actor;
//#my-bounded-untyped-actor
import akka.dispatch.BoundedMessageQueueSemantics;
import akka.dispatch.RequiresMessageQueue;
public class MyBoundedUntypedActor extends MyUntypedActor
implements RequiresMessageQueue<BoundedMessageQueueSemantics> {
}
//#my-bounded-untyped-actor

View file

@ -30,6 +30,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
//#imports-custom
//#imports-required-mailbox
//#imports-required-mailbox
import docs.actor.MyBoundedUntypedActor;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@ -48,8 +53,8 @@ public class DispatcherDocTestBase {
@BeforeClass
public static void beforeAll() {
system = ActorSystem.create("MySystem",
ConfigFactory.parseString(
DispatcherDocSpec.config()).withFallback(AkkaSpec.testConf()));
ConfigFactory.parseString(DispatcherDocSpec.javaConfig()).withFallback(
ConfigFactory.parseString(DispatcherDocSpec.config())).withFallback(AkkaSpec.testConf()));
}
@AfterClass
@ -96,6 +101,33 @@ public class DispatcherDocTestBase {
//#lookup
}
@SuppressWarnings("unused")
@Test
public void defineMailboxInConfig() {
//#defining-mailbox-in-config
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class),
"priomailboxactor");
//#defining-mailbox-in-config
}
@SuppressWarnings("unused")
@Test
public void defineMailboxInCode() {
//#defining-mailbox-in-code
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class)
.withMailbox("prio-mailbox"));
//#defining-mailbox-in-code
}
@SuppressWarnings("unused")
@Test
public void usingARequiredMailbox() {
ActorRef myActor =
system.actorOf(Props.create(MyBoundedUntypedActor.class));
}
@Test
public void priorityDispatcher() throws Exception {
JavaTestKit probe = new JavaTestKit(system);

View file

@ -202,14 +202,55 @@ And then an example on how you would use it:
.. includecode:: ../java/code/docs/dispatcher/DispatcherDocTestBase.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/DispatcherDocTestBase.java#defining-mailbox-in-config
Or code like this:
.. includecode:: code/docs/dispatcher/DispatcherDocTestBase.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::
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 using this mailbox type; the
mailbox type will be instantiated once for each dispatcher using it.
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 an error will be logged.
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -220,7 +261,8 @@ An example is worth a thousand quacks:
.. includecode:: code/docs/dispatcher/DispatcherDocTestBase.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.
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::
@ -228,8 +270,9 @@ And then you just specify the FQCN of your MailboxType as the value of the "mail
``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 using this mailbox type; the
mailbox type will be instantiated once for each dispatcher using it.
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``

View file

@ -245,12 +245,13 @@ directives are part of the :class:`Act` trait):
.. includecode:: ../../../akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala#supervise-with
Last but not least there is a little bit of convenience magic built-in, which
detects if the runtime class of the statically given actor subtype extends the
:class:`Stash` trait (this is a complicated way of saying that ``new Act with
Stash`` would not work because its runtime erased type is just an anonymous
subtype of ``Act``). The purpose is to automatically use a dispatcher with the
appropriate deque-based mailbox, ``akka.actor.default-stash-dispatcher``.
:class:`RequiresMessageQueue` trait via the :class:`Stash` trait (this is a
complicated way of saying that ``new Act with Stash`` would not work because its
runtime erased type is just an anonymous subtype of ``Act``). The purpose is to
automatically use the appropriate deque-based mailbox type required by :class:`Stash`.
If you want to use this magic, simply extend :class:`ActWithStash`:
.. includecode:: ../../../akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala#act-with-stash

View file

@ -12,8 +12,25 @@ import akka.event.Logging
import akka.event.LoggingAdapter
import scala.concurrent.duration._
import akka.actor._
import docs.dispatcher.DispatcherDocSpec.MyBoundedActor
object DispatcherDocSpec {
val javaConfig = """
//#prio-dispatcher-config-java
prio-dispatcher {
mailbox-type = "docs.dispatcher.DispatcherDocTestBase$MyPrioMailbox"
//Other dispatcher configuration goes here
}
//#prio-dispatcher-config-java
//#prio-mailbox-config-java
prio-mailbox {
mailbox-type = "docs.dispatcher.DispatcherDocSpec$MyPrioMailbox"
//Other mailbox configuration goes here
}
//#prio-mailbox-config-java
"""
val config = """
//#my-dispatcher-config
my-dispatcher {
@ -74,7 +91,7 @@ object DispatcherDocSpec {
core-pool-size-factor = 8.0
max-pool-size-factor = 16.0
}
# Specifies the bounded capacity of the mailbox queue
# Specifies the bounded capacity of the message queue
mailbox-capacity = 100
throughput = 3
}
@ -94,15 +111,9 @@ object DispatcherDocSpec {
//#prio-dispatcher-config
prio-dispatcher {
mailbox-type = "docs.dispatcher.DispatcherDocSpec$MyPrioMailbox"
}
//#prio-dispatcher-config
//#prio-dispatcher-config-java
prio-dispatcher-java {
mailbox-type = "docs.dispatcher.DispatcherDocTestBase$MyPrioMailbox"
//Other dispatcher configuration goes here
}
//#prio-dispatcher-config-java
//#prio-dispatcher-config
//#dispatcher-deployment-config
akka.actor.deployment {
@ -111,6 +122,38 @@ object DispatcherDocSpec {
}
}
//#dispatcher-deployment-config
//#prio-mailbox-config
prio-mailbox {
mailbox-type = "docs.dispatcher.DispatcherDocSpec$MyPrioMailbox"
//Other mailbox configuration goes here
}
//#prio-mailbox-config
//#mailbox-deployment-config
akka.actor.deployment {
/priomailboxactor {
mailbox = prio-mailbox
}
}
//#mailbox-deployment-config
//#bounded-mailbox-config
bounded-mailbox {
mailbox-type = "akka.dispatch.BoundedMailbox"
mailbox-capacity = 1000
mailbox-push-timeout-time = 10s
}
//#bounded-mailbox-config
//#required-mailbox-config
akka.actor.mailbox.requirements {
"akka.dispatch.BoundedMessageQueueSemantics" = bounded-mailbox
}
//#required-mailbox-config
"""
//#prio-mailbox
@ -144,6 +187,13 @@ object DispatcherDocSpec {
}
}
//#required-mailbox-class
import akka.dispatch.RequiresMessageQueue
import akka.dispatch.BoundedMessageQueueSemantics
class MyBoundedActor extends MyActor with RequiresMessageQueue[BoundedMessageQueueSemantics]
//#required-mailbox-class
//#mailbox-implementation-example
class MyUnboundedMailbox extends akka.dispatch.MailboxType {
import akka.actor.{ ActorRef, ActorSystem }
@ -209,6 +259,27 @@ class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) {
//#lookup
}
"defining mailbox in config" in {
val context = system
//#defining-mailbox-in-config
import akka.actor.Props
val myActor = context.actorOf(Props[MyActor], "priomailboxactor")
//#defining-mailbox-in-config
}
"defining mailbox in code" in {
val context = system
//#defining-mailbox-in-code
import akka.actor.Props
val myActor = context.actorOf(Props[MyActor].withMailbox("prio-mailbox"))
//#defining-mailbox-in-code
}
"using a required mailbox" in {
val context = system
val myActor = context.actorOf(Props[MyBoundedActor])
}
"defining priority dispatcher" in {
new AnyRef {
//#prio-dispatcher

View file

@ -204,6 +204,56 @@ 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 an error will be logged.
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -211,7 +261,8 @@ 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.
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::
@ -219,8 +270,10 @@ And then you just specify the FQCN of your MailboxType as the value of the "mail
``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 using this mailbox type; the
mailbox type will be instantiated once for each dispatcher using it.
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``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^