Merge remote-tracking branch 'origin/master' into wip-1644-programmatic-deploy-∂π
This commit is contained in:
commit
45140b465e
306 changed files with 14713 additions and 11320 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
=============
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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 child’s 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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue