add preprocessor for RST docs, see #2461 and #2431

The idea is to filter the sources, replacing @<var>@ occurrences with
the mapping for <var> (which is currently hard-coded). @@ -> @. In order
to make this work, I had to move the doc sources one directory down
(into akka-docs/rst) so that the filtered result could be in a sibling
directory so that relative links (to _sphinx plugins or real code) would
continue to work.

While I was at it I also changed it so that WARNINGs and ERRORs are not
swallowed into the debug dump anymore but printed at [warn] level
(minimum).

One piece of fallout is that the (online) html build is now run after
the normal one, not in parallel.
This commit is contained in:
Roland 2012-09-21 10:47:58 +02:00
parent c0f60da8cc
commit 9bc01ae265
266 changed files with 270 additions and 182 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,13 @@
.. _camel-module:
#######
Camel
#######
.. note::
The Akka Camel module has not been migrated to Akka 2.1-SNAPSHOT yet.
It might not make it into Akka 2.0 final but will then hopefully be
re-introduce in an upcoming release. It might also be backported to
2.0 final.

View file

@ -0,0 +1,138 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.actor.mailbox
import language.postfixOps
//#imports
import akka.actor.Props
//#imports
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
import org.scalatest.matchers.MustMatchers
import akka.testkit.AkkaSpec
import akka.actor.{ Actor, ExtendedActorSystem }
class MyActor extends Actor {
def receive = {
case x
}
}
object DurableMailboxDocSpec {
val config = """
//#dispatcher-config
my-dispatcher {
mailbox-type = akka.actor.mailbox.filebased.FileBasedMailboxType
}
//#dispatcher-config
"""
}
class DurableMailboxDocSpec extends AkkaSpec(DurableMailboxDocSpec.config) {
"configuration of dispatcher with durable mailbox" in {
//#dispatcher-config-use
val myActor = system.actorOf(Props[MyActor].
withDispatcher("my-dispatcher"), name = "myactor")
//#dispatcher-config-use
}
}
//#custom-mailbox
import com.typesafe.config.Config
import akka.actor.ActorContext
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.dispatch.Envelope
import akka.dispatch.MailboxType
import akka.dispatch.MessageQueue
import akka.actor.mailbox.DurableMessageQueue
import akka.actor.mailbox.DurableMessageSerialization
import akka.pattern.CircuitBreaker
import scala.concurrent.util.duration._
class MyMailboxType(systemSettings: ActorSystem.Settings, config: Config)
extends MailboxType {
override def create(owner: Option[ActorRef], system: Option[ActorSystem]): MessageQueue = (owner zip system) headOption match {
case Some((o, s: ExtendedActorSystem)) new MyMessageQueue(o, s)
case _ throw new IllegalArgumentException("requires an owner (i.e. does not work with BalancingDispatcher)")
}
}
class MyMessageQueue(_owner: ActorRef, _system: ExtendedActorSystem)
extends DurableMessageQueue(_owner, _system) with DurableMessageSerialization {
val storage = new QueueStorage
// A real-world implmentation would use configuration to set the last
// three parameters below
val breaker = CircuitBreaker(system.scheduler, 5, 30.seconds, 1.minute)
def enqueue(receiver: ActorRef, envelope: Envelope): Unit = breaker.withSyncCircuitBreaker {
val data: Array[Byte] = serialize(envelope)
storage.push(data)
}
def dequeue(): Envelope = breaker.withSyncCircuitBreaker {
val data: Option[Array[Byte]] = storage.pull()
data.map(deserialize).orNull
}
def hasMessages: Boolean = breaker.withSyncCircuitBreaker { !storage.isEmpty }
def numberOfMessages: Int = breaker.withSyncCircuitBreaker { storage.size }
/**
* Called when the mailbox is disposed.
* An ordinary mailbox would send remaining messages to deadLetters,
* but the purpose of a durable mailbox is to continue
* with the same message queue when the actor is started again.
*/
def cleanUp(owner: ActorRef, deadLetters: MessageQueue): Unit = ()
}
//#custom-mailbox
// dummy
class QueueStorage {
import java.util.concurrent.ConcurrentLinkedQueue
val queue = new ConcurrentLinkedQueue[Array[Byte]]
def push(data: Array[Byte]): Unit = queue.offer(data)
def pull(): Option[Array[Byte]] = Option(queue.poll())
def isEmpty: Boolean = queue.isEmpty
def size: Int = queue.size
}
//#custom-mailbox-test
import akka.actor.mailbox.DurableMailboxSpec
object MyMailboxSpec {
val config = """
MyStorage-dispatcher {
mailbox-type = docs.actor.mailbox.MyMailboxType
}
"""
}
class MyMailboxSpec extends DurableMailboxSpec("MyStorage", MyMailboxSpec.config) {
override def atStartup() {
}
override def atTermination() {
}
"MyMailbox" must {
"deliver a message" in {
val actor = createMailboxTestActor()
implicit val sender = testActor
actor ! "hello"
expectMsg("hello")
}
// add more tests
}
}

View file

@ -0,0 +1,8 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.actor.mailbox
import org.scalatest.junit.JUnitSuite
class DurableMailboxDocTest extends DurableMailboxDocTestBase with JUnitSuite

View file

@ -0,0 +1,50 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.actor.mailbox;
//#imports
import akka.actor.Props;
import akka.actor.ActorRef;
//#imports
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import akka.testkit.AkkaSpec;
import com.typesafe.config.ConfigFactory;
import akka.actor.ActorSystem;
import akka.actor.UntypedActor;
public class DurableMailboxDocTestBase {
ActorSystem system;
@Before
public void setUp() {
system = ActorSystem.create("MySystem",
ConfigFactory.parseString(DurableMailboxDocSpec.config()).withFallback(AkkaSpec.testConf()));
}
@After
public void tearDown() {
system.shutdown();
}
@Test
public void configDefinedDispatcher() {
//#dispatcher-config-use
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class).
withDispatcher("my-dispatcher"), "myactor");
//#dispatcher-config-use
myActor.tell("test", null);
}
public static class MyUntypedActor extends UntypedActor {
public void onReceive(Object message) {
}
}
}

View file

@ -0,0 +1,104 @@
.. _durable-mailboxes:
###################
Durable Mailboxes
###################
Overview
========
A durable mailbox is a mailbox which stores the messages on durable storage.
What this means in practice is that if there are pending messages in the actor's
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.
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
storage. Read more about that in the :ref:`dispatchers-scala` documentation.
One basic file based durable mailbox is provided by Akka out-of-the-box.
Other implementations can easily be added. Some are available as separate community
Open Source projects, such as:
* `AMQP Durable Mailbox <https://github.com/drexin/akka-amqp-mailbox>`_
A durable mailbox is like any other mailbox not likely to be transactional. It's possible
if the actor crashes after receiving a message, but before completing processing of
it, that the message could be lost.
.. warning::
A durable mailbox typically doesn't work with blocking message send, i.e. the message
send operations that are relying on futures; ``?`` or ``ask``. If the node
has crashed and then restarted, the thread that was blocked waiting for the
reply is gone and there is no way we can deliver the message.
File-based durable mailbox
==========================
This mailbox is backed by a journaling transaction log on the local file
system. It is the simplest to use since it does not require an extra
infrastructure piece to administer, but it is usually sufficient and just what
you need.
In the configuration of the dispatcher you specify the fully qualified class name
of the mailbox:
.. includecode:: code/docs/actor/mailbox/DurableMailboxDocSpec.scala
:include: dispatcher-config
Here is an example of how to create an actor with a durable dispatcher, in Scala:
.. includecode:: code/docs/actor/mailbox/DurableMailboxDocSpec.scala
:include: imports,dispatcher-config-use
Corresponding example in Java:
.. includecode:: code/docs/actor/mailbox/DurableMailboxDocTestBase.java
:include: imports,dispatcher-config-use
You can also configure and tune the file-based durable mailbox. This is done in
the ``akka.actor.mailbox.file-based`` section in the :ref:`configuration`.
.. literalinclude:: ../../../akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf
:language: none
How to implement a durable mailbox
==================================
Here is an example of how to implement a custom durable mailbox. Essentially it consists of
a configurator (MailboxType) and a queue implementation (DurableMessageQueue).
The envelope contains the message sent to the actor, and information about sender. It is the
envelope that needs to be stored. As a help utility you can mixin DurableMessageSerialization
to serialize and deserialize the envelope using the ordinary :ref:`serialization-scala`
mechanism. This optional and you may store the envelope data in any way you like. Durable
mailboxes are an excellent fit for usage of circuit breakers. These are described in the
:ref:`circuit-breaker` documentation.
.. includecode:: code/docs/actor/mailbox/DurableMailboxDocSpec.scala
:include: custom-mailbox
To facilitate testing of a durable mailbox you may use ``DurableMailboxSpec`` as base class.
It implements a few basic tests and helps you setup the a fixture. More tests can be
added in concrete subclass like this:
.. includecode:: code/docs/actor/mailbox/DurableMailboxDocSpec.scala
:include: custom-mailbox-test
You find DurableMailboxDocSpec in ``akka-mailboxes-common-test-2.1-SNAPSHOT.jar``.
Add this dependency::
"com.typesafe.akka" % "akka-mailboxes-common-test" % "2.1-SNAPSHOT"
For more inspiration you can look at the old implementations based on Redis, MongoDB, Beanstalk,
and ZooKeeper, which can be found in Akka git repository tag
`v2.0.1 <https://github.com/akka/akka/tree/v2.0.1/akka-durable-mailboxes>`_.

View file

@ -0,0 +1,38 @@
.. _http-module:
HTTP
####
Play2 Mini
==========
The Akka team recommends the `Play2 Mini <https://github.com/typesafehub/play2-mini>`_ framework when building RESTful
service applications that integrates with Akka. It provides a REST API on top of `Play2 <https://github.com/playframework/Play20/>`_.
Getting started
---------------
Easiest way to get started with `Play2 Mini <https://github.com/typesafehub/play2-mini>`_ is to use the
G8 project templates, as described in the `Play2 Mini Documentation <https://github.com/typesafehub/play2-mini>`_.
If you already have an Akka project and want to add Play2 Mini, you must first add the following to
your ``libraryDependencies``::
libraryDependencies += "com.typesafe" %% "play-mini" % "<version-number>"
In case you need to start Play2 Mini programatically you can use::
play.core.server.NettyServer.main(Array())
Akka Mist
=========
If you are using Akka Mist (Akka's old HTTP/REST module) with Akka 1.x and wish to upgrade to 2.x
there is now a port of Akka Mist to Akka 2.x. You can find it `here <https://github.com/thenewmotion/akka-http>`_.
Other Alternatives
==================
There are a bunch of other alternatives for using Akka with HTTP/REST. You can find some of them
among the `Community Projects <http://akka.io/community>`_.

View file

@ -0,0 +1,9 @@
Modules
=======
.. toctree::
:maxdepth: 2
durable-mailbox
http
camel