Merge remote-tracking branch 'origin/master' into wip-1644-programmatic-deploy-∂π

This commit is contained in:
Roland 2012-02-03 09:49:04 +01:00
commit 45140b465e
306 changed files with 14713 additions and 11320 deletions

View file

@ -657,3 +657,7 @@ extend that, either through inheritance or delegation, is to use
``PartialFunction.orElse`` chaining.
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-orElse
Or:
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-orElse2

View file

@ -133,6 +133,29 @@ class SpecificActor extends GenericActor {
case class MyMsg(subject: String)
//#receive-orElse
//#receive-orElse2
trait ComposableActor extends Actor {
private var receives: List[Receive] = List()
protected def registerReceive(receive: Receive) {
receives = receive :: receives
}
def receive = receives reduce { _ orElse _ }
}
class MyComposableActor extends ComposableActor {
override def preStart() {
registerReceive({
case "foo" /* Do something */
})
registerReceive({
case "bar" /* Do something */
})
}
}
//#receive-orElse2
class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"import context" in {
@ -314,7 +337,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"using pattern ask / pipeTo" in {
val actorA, actorB, actorC, actorD = system.actorOf(Props.empty)
//#ask-pipeTo
import akka.pattern.{ ask, pipeTo }
import akka.pattern.{ ask, pipe }
case class Result(x: Int, s: String, d: Double)
case object Request
@ -329,7 +352,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
} yield Result(x, s, d)
f pipeTo actorD // .. or ..
pipeTo(f, actorD)
pipe(f) to actorD
//#ask-pipeTo
}

View file

@ -11,7 +11,7 @@ import akka.util.duration._
import akka.util.Duration
import akka.util.Timeout
import akka.event.LoggingReceive
import akka.pattern.ask
import akka.pattern.{ ask, pipe }
import com.typesafe.config.ConfigFactory
//#imports

View file

@ -22,12 +22,17 @@ object DispatcherDocSpec {
my-dispatcher {
# Dispatcher is the name of the event-based dispatcher
type = Dispatcher
# minimum number of threads to cap factor-based core number to
core-pool-size-min = 2
# No of core threads ... ceil(available processors * factor)
core-pool-size-factor = 2.0
# maximum number of threads to cap factor-based number to
core-pool-size-max = 10
# What kind of ExecutionService to use
executor = "thread-pool-executor"
# Configuration for the thread pool
thread-pool-executor {
# minimum number of threads to cap factor-based core number to
core-pool-size-min = 2
# No of core threads ... ceil(available processors * factor)
core-pool-size-factor = 2.0
# maximum number of threads to cap factor-based number to
core-pool-size-max = 10
}
# Throughput defines the number of messages that are processed in a batch before the
# thread is returned to the pool. Set to 1 for as fair as possible.
throughput = 100
@ -37,8 +42,11 @@ object DispatcherDocSpec {
//#my-bounded-config
my-dispatcher-bounded-queue {
type = Dispatcher
core-pool-size-factor = 8.0
max-pool-size-factor = 16.0
executor = "thread-pool-executor"
thread-pool-executor {
core-pool-size-factor = 8.0
max-pool-size-factor = 16.0
}
# Specifies the bounded capacity of the mailbox queue
mailbox-capacity = 100
throughput = 3
@ -48,6 +56,11 @@ object DispatcherDocSpec {
//#my-balancing-config
my-balancing-dispatcher {
type = BalancingDispatcher
executor = "thread-pool-executor"
thread-pool-executor {
core-pool-size-factor = 8.0
max-pool-size-factor = 16.0
}
}
//#my-balancing-config

View file

@ -41,6 +41,15 @@ object CountExtension
//#extensionid
object ExtensionDocSpec {
val config = """
//#config
akka {
extensions = ["akka.docs.extension.CountExtension$"]
}
//#config
"""
//#extension-usage-actor
class MyActor extends Actor {
@ -64,7 +73,7 @@ object ExtensionDocSpec {
//#extension-usage-actor-trait
}
class ExtensionDocSpec extends AkkaSpec {
class ExtensionDocSpec extends AkkaSpec(ExtensionDocSpec.config) {
import ExtensionDocSpec._
"demonstrate how to create an extension in Scala" in {
@ -73,4 +82,10 @@ class ExtensionDocSpec extends AkkaSpec {
//#extension-usage
}
"demonstrate how to lookup a configured extension in Scala" in {
//#extension-lookup
system.extension(CountExtension)
//#extension-lookup
}
}

View file

@ -13,6 +13,7 @@ import akka.dispatch.Future
import akka.dispatch.Await
import akka.util.duration._
import akka.dispatch.Promise
import java.lang.IllegalStateException
object FutureDocSpec {
@ -266,6 +267,19 @@ class FutureDocSpec extends AkkaSpec {
Await.result(future, 1 second) must be(0)
}
"demonstrate usage of recoverWith" in {
implicit val timeout = system.settings.ActorTimeout
val actor = system.actorOf(Props[MyActor])
val msg1 = -1
//#try-recover
val future = akka.pattern.ask(actor, msg1) recoverWith {
case e: ArithmeticException Promise.successful(0)
case foo: IllegalArgumentException Promise.failed[Int](new IllegalStateException("All br0ken!"))
}
//#try-recover
Await.result(future, 1 second) must be(0)
}
"demonstrate usage of zip" in {
val future1 = Future { "foo" }
val future2 = Future { "bar" }
@ -275,13 +289,28 @@ class FutureDocSpec extends AkkaSpec {
Await.result(future3, 1 second) must be("foo bar")
}
"demonstrate usage of or" in {
"demonstrate usage of andThen" in {
def loadPage(s: String) = s
val url = "foo bar"
def log(cause: Throwable) = ()
def watchSomeTV = ()
//#and-then
val result = Future { loadPage(url) } andThen {
case Left(exception) log(exception)
} andThen {
case _ watchSomeTV
}
//#and-then
Await.result(result, 1 second) must be("foo bar")
}
"demonstrate usage of fallbackTo" in {
val future1 = Future { "foo" }
val future2 = Future { "bar" }
val future3 = Future { "pigdog" }
//#or
val future4 = future1 or future2 or future3
//#or
//#fallback-to
val future4 = future1 fallbackTo future2 fallbackTo future3
//#fallback-to
Await.result(future4, 1 second) must be("foo")
}

View file

@ -89,10 +89,10 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
val fsm = TestFSMRef(new Actor with FSM[Int, String] {
startWith(1, "")
when(1) {
case Ev("go") goto(2) using "go"
case Event("go", _) goto(2) using "go"
}
when(2) {
case Ev("back") goto(1) using "back"
case Event("back", _) goto(1) using "back"
}
})

View file

@ -48,6 +48,11 @@ Loading from Configuration
To be able to load extensions from your Akka configuration you must add FQCNs of implementations of either ``ExtensionId`` or ``ExtensionIdProvider``
in the ``akka.extensions`` section of the config you provide to your ``ActorSystem``.
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
:include: config
Note that in this case ``CountExtension`` is an object and therefore the class name ends with ``$``.
Applicability
=============

View file

@ -1,5 +1,53 @@
.. _fault-tolerance-sample-scala:
Diagrams of the Fault Tolerance Sample (Scala)
----------------------------------------------
.. image:: ../images/faulttolerancesample-normal-flow.png
*The above diagram illustrates the normal message flow.*
**Normal flow:**
======= ==================================================================================
Step Description
======= ==================================================================================
1 The progress ``Listener`` starts the work.
2 The ``Worker`` schedules work by sending ``Do`` messages periodically to itself
3, 4, 5 When receiving ``Do`` the ``Worker`` tells the ``CounterService``
to increment the counter, three times. The ``Increment`` message is forwarded
to the ``Counter``, which updates its counter variable and sends current value
to the ``Storage``.
6, 7 The ``Worker`` asks the ``CounterService`` of current value of the counter and pipes
the result back to the ``Listener``.
======= ==================================================================================
.. image:: ../images/faulttolerancesample-failure-flow.png
*The above diagram illustrates what happens in case of storage failure.*
**Failure flow:**
=========== ==================================================================================
Step Description
=========== ==================================================================================
1 The ``Storage`` throws ``StorageException``.
2 The ``CounterService`` is supervisor of the ``Storage`` and restarts the
``Storage`` when ``StorageException`` is thrown.
3, 4, 5, 6 The ``Storage`` continues to fail and is restarted.
7 After 3 failures and restarts within 5 seconds the ``Storage`` is stopped by its
supervisor, i.e. the ``CounterService``.
8 The ``CounterService`` is also watching the ``Storage`` for termination and
receives the ``Terminated`` message when the ``Storage`` has been stopped ...
9, 10, 11 and tells the ``Counter`` that there is no ``Storage``.
12 The ``CounterService`` schedules a ``Reconnect`` message to itself.
13, 14 When it receives the ``Reconnect`` message it creates a new ``Storage`` ...
15, 16 and tells the the ``Counter`` to use the new ``Storage``
=========== ==================================================================================
Full Source Code of the Fault Tolerance Sample (Scala)
------------------------------------------------------

View file

@ -43,7 +43,7 @@ For the sake of demonstration let us consider the following strategy:
:include: strategy
I have chosen a few well-known exception types in order to demonstrate the
application of the fault handling actions described in :ref:`supervision`.
application of the fault handling directives described in :ref:`supervision`.
First off, it is a one-for-one strategy, meaning that each child is treated
separately (an all-for-one strategy works very similarly, the only difference
is that any decision is applied to all children of the supervisor, not only the
@ -53,8 +53,8 @@ that the respective limit does not apply, leaving the possibility to specify an
absolute upper limit on the restarts or to make the restarts work infinitely.
The match statement which forms the bulk of the body is of type ``Decider``,
which is a ``PartialFunction[Throwable, Action]``. This
is the piece which maps child failure types to their corresponding actions.
which is a ``PartialFunction[Throwable, Directive]``. This
is the piece which maps child failure types to their corresponding directives.
Default Supervisor Strategy
---------------------------
@ -76,7 +76,7 @@ in the same way as the default strategy defined above.
Test Application
----------------
The following section shows the effects of the different actions in practice,
The following section shows the effects of the different directives in practice,
wherefor a test setup is needed. First off, we need a suitable supervisor:
.. includecode:: code/akka/docs/actor/FaultHandlingDocSpec.scala
@ -99,13 +99,13 @@ Let us create actors:
.. includecode:: code/akka/docs/actor/FaultHandlingDocSpec.scala
:include: create
The first test shall demonstrate the ``Resume`` action, so we try it out by
The first test shall demonstrate the ``Resume`` directive, so we try it out by
setting some non-initial state in the actor and have it fail:
.. includecode:: code/akka/docs/actor/FaultHandlingDocSpec.scala
:include: resume
As you can see the value 42 survives the fault handling action. Now, if we
As you can see the value 42 survives the fault handling directive. Now, if we
change the failure to a more serious ``NullPointerException``, that will no
longer be the case:
@ -119,7 +119,7 @@ terminated by the supervisor:
:include: stop
Up to now the supervisor was completely unaffected by the childs failure,
because the actions set did handle it. In case of an ``Exception``, this is not
because the directives set did handle it. In case of an ``Exception``, this is not
true anymore and the supervisor escalates the failure.
.. includecode:: code/akka/docs/actor/FaultHandlingDocSpec.scala
@ -129,7 +129,7 @@ The supervisor itself is supervised by the top-level actor provided by the
:class:`ActorSystem`, which has the default policy to restart in case of all
``Exception`` cases (with the notable exceptions of
``ActorInitializationException`` and ``ActorKilledException``). Since the
default action in case of a restart is to kill all children, we expected our poor
default directive in case of a restart is to kill all children, we expected our poor
child not to survive this failure.
In case this is not desired (which depends on the use case), we need to use a

View file

@ -178,7 +178,7 @@ demonstrated below:
.. code-block:: scala
when(Idle) {
case Ev(Start(msg)) => // convenience extractor when state data not needed
case Event(Start(msg), _) =>
goto(Timer) using (msg, sender)
}
@ -188,9 +188,8 @@ demonstrated below:
goto(Idle)
}
The :class:`Event(msg, data)` case class may be used directly in the pattern as
shown in state Idle, or you may use the extractor :obj:`Ev(msg)` when the state
data are not needed.
The :class:`Event(msg: Any, data: D)` case class is parameterized with the data
type held by the FSM for convenient pattern matching.
Defining the Initial State
--------------------------
@ -216,7 +215,7 @@ do something else in this case you can specify that with
case Event(x : X, data) =>
log.info(this, "Received unhandled event: " + x)
stay
case Ev(msg) =>
case Event(msg, _) =>
log.warn(this, "Received unknown event: " + x)
goto(Error)
}
@ -259,7 +258,7 @@ All modifier can be chained to achieve a nice and concise description:
.. code-block:: scala
when(State) {
case Ev(msg) =>
case Event(msg, _) =>
goto(Processing) using (msg) forMax (5 seconds) replying (WillDo)
}
@ -396,7 +395,7 @@ state data which is available during termination handling.
.. code-block:: scala
when(A) {
case Ev(Stop) =>
case Event(Stop, _) =>
doCleanup()
stop()
}

View file

@ -198,14 +198,26 @@ For this Akka supports ``onComplete``, ``onSuccess`` and ``onFailure``, of which
.. includecode:: code/akka/docs/future/FutureDocSpec.scala
:include: onComplete
Ordering
--------
Since callbacks are executed in any order and potentially in parallel,
it can be tricky at the times when you need sequential ordering of operations.
But there's a solution! And it's name is ``andThen``, and it creates a new Future with
the specified callback, a Future that will have the same result as the Future it's called on,
which allows for ordering like in the following sample:
.. includecode:: code/akka/docs/future/FutureDocSpec.scala
:include: and-then
Auxiliary methods
-----------------
``Future`` ``or`` combines 2 Futures into a new ``Future``, and will hold the successful value of the second ``Future`
``Future`` ``fallbackTo`` combines 2 Futures into a new ``Future``, and will hold the successful value of the second ``Future`
if the first ``Future`` fails.
.. includecode:: code/akka/docs/future/FutureDocSpec.scala
:include: or
:include: fallback-to
You can also combine two Futures into a new ``Future`` that will hold a tuple of the two Futures successful results,
using the ``zip`` operation.
@ -232,3 +244,9 @@ our ``Future`` would have a result of 0. The ``recover`` method works very simil
so multiple ``Exception``\s can be handled in this manner, and if an ``Exception`` is not handled this way
it will behave as if we hadn't used the ``recover`` method.
You can also use the ``recoverWith`` method, which has the same relationship to ``recover`` as ``flatMap` has to ``map``,
and is use like this:
.. includecode:: code/akka/docs/future/FutureDocSpec.scala
:include: try-recover

View file

@ -26,7 +26,7 @@ to your ``application.conf`` file::
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
transport = "akka.remote.netty.NettyRemoteSupport"
transport = "akka.remote.netty.NettyRemoteTransport"
server {
hostname = "127.0.0.1"
port = 2552