Merge with master
This commit is contained in:
commit
009853f2f6
168 changed files with 2942 additions and 6005 deletions
|
|
@ -40,7 +40,7 @@ along with the implementation of how the messages should be processed.
|
|||
|
||||
Here is an example:
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala
|
||||
:include: imports1,my-actor
|
||||
|
||||
Please note that the Akka Actor ``receive`` message loop is exhaustive, which is
|
||||
|
|
@ -53,8 +53,8 @@ thrown and the actor is restarted when an unknown message is received.
|
|||
Creating Actors with default constructor
|
||||
----------------------------------------
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala
|
||||
:include: imports2,system-actorOf
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala
|
||||
:include: imports2,system-actorOf
|
||||
|
||||
The call to :meth:`actorOf` returns an instance of ``ActorRef``. This is a handle to
|
||||
the ``Actor`` instance which you can use to interact with the ``Actor``. The
|
||||
|
|
@ -70,7 +70,7 @@ how the supervisor hierarchy is arranged. When using the context the current act
|
|||
will be supervisor of the created child actor. When using the system it will be
|
||||
a top level actor, that is supervised by the system (internal guardian actor).
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#context-actorOf
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#context-actorOf
|
||||
|
||||
Actors are automatically started asynchronously when created.
|
||||
When you create the ``Actor`` then it will automatically call the ``preStart``
|
||||
|
|
@ -92,16 +92,24 @@ a call-by-name block in which you can create the Actor in any way you like.
|
|||
|
||||
Here is an example:
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#creating-constructor
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#creating-constructor
|
||||
|
||||
|
||||
Props
|
||||
-----
|
||||
|
||||
``Props`` is a configuration class to specify options for the creation
|
||||
of actors. Here are some examples on how to create a ``Props`` instance.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#creating-props-config
|
||||
|
||||
|
||||
Creating Actors with Props
|
||||
--------------------------
|
||||
|
||||
``Props`` is a configuration object to specify additional things for the actor to
|
||||
be created, such as the ``MessageDispatcher``.
|
||||
Actors are created by passing in a ``Props`` instance into the ``actorOf`` factory method.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#creating-props
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#creating-props
|
||||
|
||||
|
||||
Creating Actors using anonymous classes
|
||||
|
|
@ -109,7 +117,7 @@ Creating Actors using anonymous classes
|
|||
|
||||
When spawning actors for specific sub-tasks from within an actor, it may be convenient to include the code to be executed directly in place, using an anonymous class.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#anonymous-actor
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#anonymous-actor
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
@ -145,13 +153,16 @@ In addition, it offers:
|
|||
|
||||
You can import the members in the :obj:`context` to avoid prefixing access with ``context.``
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#import-context
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#import-context
|
||||
|
||||
The remaining visible methods are user-overridable life-cycle hooks which are
|
||||
described in the following::
|
||||
|
||||
def preStart() {}
|
||||
def preRestart(reason: Throwable, message: Option[Any]) { postStop() }
|
||||
def preRestart(reason: Throwable, message: Option[Any]) {
|
||||
context.children foreach (context.stop(_))
|
||||
postStop()
|
||||
}
|
||||
def postRestart(reason: Throwable) { preStart() }
|
||||
def postStop() {}
|
||||
|
||||
|
|
@ -185,7 +196,7 @@ processing a message. This restart involves the hooks mentioned above:
|
|||
message, e.g. when a supervisor does not trap the exception and is restarted
|
||||
in turn by its supervisor. This method is the best place for cleaning up,
|
||||
preparing hand-over to the fresh actor instance, etc.
|
||||
By default it calls :meth:`postStop`.
|
||||
By default it stops all children and calls :meth:`postStop`.
|
||||
2. The initial factory from the ``actorOf`` call is used
|
||||
to produce the fresh instance.
|
||||
3. The new actor’s :meth:`postRestart` method is invoked with the exception
|
||||
|
|
@ -287,7 +298,7 @@ To complete the future with an exception you need send a Failure message to the
|
|||
This is not done automatically when an actor throws an exception while processing a
|
||||
message.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#reply-exception
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#reply-exception
|
||||
|
||||
If the actor does not complete the future, it will expire after the timeout period,
|
||||
which is taken from one of the following locations in order of precedence:
|
||||
|
|
@ -336,7 +347,7 @@ type, it will throw the exception or a :class:`ClassCastException` (if you want
|
|||
to get :obj:`None` in the latter case, use :meth:`Future.asSilently[T]`). In
|
||||
case of a timeout, :obj:`None` is returned.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#using-ask
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#using-ask
|
||||
|
||||
Forward message
|
||||
---------------
|
||||
|
|
@ -368,7 +379,7 @@ This method should return a ``PartialFunction``, e.g. a ‘match/case’ clause
|
|||
which the message can be matched against the different case clauses using Scala
|
||||
pattern matching. Here is an example:
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala
|
||||
:include: imports1,my-actor
|
||||
|
||||
|
||||
|
|
@ -398,19 +409,17 @@ received within a certain time. To receive this timeout you have to set the
|
|||
``receiveTimeout`` property and declare a case handing the ReceiveTimeout
|
||||
object.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#receive-timeout
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-timeout
|
||||
|
||||
|
||||
Stopping actors
|
||||
===============
|
||||
|
||||
Actors are stopped by invoking the ``stop`` method of the ``ActorRef``.
|
||||
The actual termination of the actor is performed asynchronously, i.e.
|
||||
``stop`` may return before the actor is stopped.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
actor.stop()
|
||||
Actors are stopped by invoking the :meth:`stop` method of a ``ActorRefFactory``,
|
||||
i.e. ``ActorContext`` or ``ActorSystem``. Typically the context is used for stopping
|
||||
child actors and the system for stopping top level actors. The actual termination of
|
||||
the actor is performed asynchronously, i.e. :meth:`stop` may return before the actor is
|
||||
stopped.
|
||||
|
||||
Processing of the current message, if any, will continue before the actor is stopped,
|
||||
but additional messages in the mailbox will not be processed. By default these
|
||||
|
|
@ -464,7 +473,7 @@ pushed and popped.
|
|||
|
||||
To hotswap the Actor behavior using ``become``:
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#hot-swap-actor
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#hot-swap-actor
|
||||
|
||||
The ``become`` method is useful for many different things, but a particular nice
|
||||
example of it is in example where it is used to implement a Finite State Machine
|
||||
|
|
@ -474,12 +483,12 @@ example of it is in example where it is used to implement a Finite State Machine
|
|||
|
||||
Here is another little cute example of ``become`` and ``unbecome`` in action:
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#swapper
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#swapper
|
||||
|
||||
Encoding Scala Actors nested receives without accidentally leaking memory
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
See this `Unnested receive example <http://github.com/jboner/akka/blob/master/akka/akka-docs/scala/code/UnnestedReceives.scala>`_.
|
||||
See this `Unnested receive example <http://github.com/jboner/akka/blob/master/akka/akka-docs/scala/code/akka/docs/actor/UnnestedReceives.scala>`_.
|
||||
|
||||
|
||||
Downgrade
|
||||
|
|
@ -555,4 +564,4 @@ A bit advanced but very useful way of defining a base message handler and then
|
|||
extend that, either through inheritance or delegation, is to use
|
||||
``PartialFunction.orElse`` chaining.
|
||||
|
||||
.. includecode:: code/ActorDocSpec.scala#receive-orElse
|
||||
.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-orElse
|
||||
|
|
|
|||
|
|
@ -1,147 +1,4 @@
|
|||
Agents (Scala)
|
||||
==============
|
||||
|
||||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Agents in Akka were inspired by `agents in Clojure <http://clojure.org/agents>`_.
|
||||
|
||||
Agents provide asynchronous change of individual locations. Agents are bound to a single storage location for their lifetime, and only allow mutation of that location (to a new state) to occur as a result of an action. Update actions are functions that are asynchronously applied to the Agent's state and whose return value becomes the Agent's new state. The state of an Agent should be immutable.
|
||||
|
||||
While updates to Agents are asynchronous, the state of an Agent is always immediately available for reading by any thread (using ``get`` or ``apply``) without any messages.
|
||||
|
||||
Agents are reactive. The update actions of all Agents get interleaved amongst threads in a thread pool. At any point in time, at most one ``send`` action for each Agent is being executed. Actions dispatched to an agent from another thread will occur in the order they were sent, potentially interleaved with actions dispatched to the same agent from other sources.
|
||||
|
||||
If an Agent is used within an enclosing transaction, then it will participate in that transaction. Agents are integrated with the STM - any dispatches made in a transaction are held until that transaction commits, and are discarded if it is retried or aborted.
|
||||
|
||||
Creating and stopping Agents
|
||||
----------------------------
|
||||
|
||||
Agents are created by invoking ``Agent(value)`` passing in the Agent's initial value.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val agent = Agent(5)
|
||||
|
||||
An Agent will be running until you invoke ``close`` on it. Then it will be eligible for garbage collection (unless you hold on to it in some way).
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
agent.close()
|
||||
|
||||
Updating Agents
|
||||
---------------
|
||||
|
||||
You update an Agent by sending a function that transforms the current value or by sending just a new value. The Agent will apply the new value or function atomically and asynchronously. The update is done in a fire-forget manner and you are only guaranteed that it will be applied. There is no guarantee of when the update will be applied but dispatches to an Agent from a single thread will occur in order. You apply a value or a function by invoking the ``send`` function.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
// send a value
|
||||
agent send 7
|
||||
|
||||
// send a function
|
||||
agent send (_ + 1)
|
||||
agent send (_ * 2)
|
||||
|
||||
You can also dispatch a function to update the internal state but on its own thread. This does not use the reactive thread pool and can be used for long-running or blocking operations. You do this with the ``sendOff`` method. Dispatches using either ``sendOff`` or ``send`` will still be executed in order.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
// sendOff a function
|
||||
agent sendOff (longRunningOrBlockingFunction)
|
||||
|
||||
Reading an Agent's value
|
||||
------------------------
|
||||
|
||||
Agents can be dereferenced, e.g. you can get an Agent's value, by invoking the Agent with parenthesis like this:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val result = agent()
|
||||
|
||||
Or by using the get method.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val result = agent.get
|
||||
|
||||
Reading an Agent's current value does not involve any message passing and happens immediately. So while updates to an Agent are asynchronous, reading the state of an Agent is synchronous.
|
||||
|
||||
Awaiting an Agent's value
|
||||
-------------------------
|
||||
|
||||
It is also possible to read the value after all currently queued ``send``\s have completed. You can do this with ``await``:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val result = agent.await
|
||||
|
||||
You can also get a ``Future`` to this value, that will be completed after the currently queued updates have completed:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val future = agent.future
|
||||
// ...
|
||||
val result = future.await.result.get
|
||||
|
||||
Transactional Agents
|
||||
--------------------
|
||||
|
||||
If an Agent is used within an enclosing transaction, then it will participate in that transaction. If you send to an Agent within a transaction then the dispatch to the Agent will be held until that transaction commits, and discarded if the transaction is aborted.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
import akka.agent.Agent
|
||||
import akka.stm._
|
||||
|
||||
def transfer(from: Agent[Int], to: Agent[Int], amount: Int): Boolean = {
|
||||
atomic {
|
||||
if (from.get < amount) false
|
||||
else {
|
||||
from send (_ - amount)
|
||||
to send (_ + amount)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val from = Agent(100)
|
||||
val to = Agent(20)
|
||||
val ok = transfer(from, to, 50)
|
||||
|
||||
from() // -> 50
|
||||
to() // -> 70
|
||||
|
||||
Monadic usage
|
||||
-------------
|
||||
|
||||
Agents are also monadic, allowing you to compose operations using for-comprehensions. In a monadic usage, new Agents are created leaving the original Agents untouched. So the old values (Agents) are still available as-is. They are so-called 'persistent'.
|
||||
|
||||
Example of a monadic usage:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
val agent1 = Agent(3)
|
||||
val agent2 = Agent(5)
|
||||
|
||||
// uses foreach
|
||||
var result = 0
|
||||
for (value <- agent1) {
|
||||
result = value + 1
|
||||
}
|
||||
|
||||
// uses map
|
||||
val agent3 =
|
||||
for (value <- agent1) yield value + 1
|
||||
|
||||
// uses flatMap
|
||||
val agent4 = for {
|
||||
value1 <- agent1
|
||||
value2 <- agent2
|
||||
} yield value1 + value2
|
||||
|
||||
agent1.close()
|
||||
agent2.close()
|
||||
agent3.close()
|
||||
agent4.close()
|
||||
The Akka Agents module has not been migrated to Akka 2.0-SNAPSHOT yet.
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
package akka.docs.stm
|
||||
|
||||
import org.scalatest.WordSpec
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
|
||||
class StmDocSpec extends WordSpec with MustMatchers {
|
||||
|
||||
"simple counter example" in {
|
||||
//#simple
|
||||
import akka.stm._
|
||||
|
||||
val ref = Ref(0)
|
||||
|
||||
def counter = atomic {
|
||||
ref alter (_ + 1)
|
||||
}
|
||||
|
||||
counter
|
||||
// -> 1
|
||||
|
||||
counter
|
||||
// -> 2
|
||||
//#simple
|
||||
|
||||
ref.get must be === 2
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import akka.actor.ActorSystem
|
|||
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import akka.testkit._
|
||||
import akka.util._
|
||||
import akka.util.duration._
|
||||
|
||||
//#my-actor
|
||||
|
|
@ -187,6 +188,23 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
|||
system.stop(myActor)
|
||||
}
|
||||
|
||||
"creating a Props config" in {
|
||||
val dispatcher = system.dispatcherFactory.lookup("my-dispatcher")
|
||||
//#creating-props-config
|
||||
import akka.actor.Props
|
||||
val props1 = Props()
|
||||
val props2 = Props[MyActor]
|
||||
val props3 = Props(new MyActor)
|
||||
val props4 = Props(
|
||||
creator = { () ⇒ new MyActor },
|
||||
dispatcher = dispatcher,
|
||||
timeout = Timeout(100))
|
||||
val props5 = props1.withCreator(new MyActor)
|
||||
val props6 = props5.withDispatcher(dispatcher)
|
||||
val props7 = props6.withTimeout(Timeout(100))
|
||||
//#creating-props-config
|
||||
}
|
||||
|
||||
"creating actor with Props" in {
|
||||
//#creating-props
|
||||
import akka.actor.Props
|
||||
53
akka-docs/scala/code/akka/docs/actor/SchedulerDocSpec.scala
Normal file
53
akka-docs/scala/code/akka/docs/actor/SchedulerDocSpec.scala
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package akka.docs.actor
|
||||
|
||||
//#imports1
|
||||
import akka.actor.Actor
|
||||
import akka.actor.Props
|
||||
import akka.util.duration._
|
||||
|
||||
//#imports1
|
||||
|
||||
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import akka.testkit._
|
||||
|
||||
class SchedulerDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
||||
"schedule a one-off task" in {
|
||||
//#schedule-one-off-message
|
||||
//Schedules to send the "foo"-message to the testActor after 50ms
|
||||
system.scheduler.scheduleOnce(50 milliseconds, testActor, "foo")
|
||||
//#schedule-one-off-message
|
||||
|
||||
expectMsg(1 second, "foo")
|
||||
|
||||
//#schedule-one-off-thunk
|
||||
//Schedules a function to be executed (send the current time) to the testActor after 50ms
|
||||
system.scheduler.scheduleOnce(50 milliseconds) {
|
||||
testActor ! System.currentTimeMillis
|
||||
}
|
||||
//#schedule-one-off-thunk
|
||||
|
||||
}
|
||||
|
||||
"schedule a recurring task" in {
|
||||
//#schedule-recurring
|
||||
val Tick = "tick"
|
||||
val tickActor = system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case Tick ⇒ //Do something
|
||||
}
|
||||
}))
|
||||
//This will schedule to send the Tick-message
|
||||
//to the tickActor after 0ms repeating every 50ms
|
||||
val cancellable =
|
||||
system.scheduler.schedule(0 milliseconds,
|
||||
50 milliseconds,
|
||||
tickActor,
|
||||
Tick)
|
||||
|
||||
//This cancels further Ticks to be sent
|
||||
cancellable.cancel()
|
||||
//#schedule-recurring
|
||||
system.stop(tickActor)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,27 +16,35 @@ object DispatcherDocSpec {
|
|||
val config = """
|
||||
//#my-dispatcher-config
|
||||
my-dispatcher {
|
||||
type = Dispatcher # Dispatcher is the name of the event-based dispatcher
|
||||
daemonic = off # Toggles whether the threads created by this dispatcher should be daemons or not
|
||||
core-pool-size-min = 2 # minimum number of threads to cap factor-based core number to
|
||||
core-pool-size-factor = 2.0 # No of core threads ... ceil(available processors * factor)
|
||||
core-pool-size-max = 10 # maximum number of threads to cap factor-based number to
|
||||
throughput = 100 # 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.
|
||||
# Dispatcher is the name of the event-based dispatcher
|
||||
type = Dispatcher
|
||||
# Toggles whether the threads created by this dispatcher should be daemons or not
|
||||
daemonic = off
|
||||
# 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
|
||||
}
|
||||
//#my-dispatcher-config
|
||||
|
||||
|
||||
//#my-bounded-config
|
||||
my-dispatcher-bounded-queue {
|
||||
type = Dispatcher
|
||||
core-pool-size-factor = 8.0
|
||||
max-pool-size-factor = 16.0
|
||||
task-queue-size = 100 # Specifies the bounded capacity of the task queue
|
||||
task-queue-type = "array" # Specifies which type of task queue will be used, can be "array" or "linked" (default)
|
||||
# Specifies the bounded capacity of the task queue
|
||||
task-queue-size = 100
|
||||
# Specifies which type of task queue will be used, can be "array" or "linked" (default)
|
||||
task-queue-type = "array"
|
||||
throughput = 3
|
||||
}
|
||||
//#my-bounded-config
|
||||
|
||||
|
||||
//#my-balancing-config
|
||||
my-balancing-dispatcher {
|
||||
type = BalancingDispatcher
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
package akka.docs.extension
|
||||
|
||||
import org.scalatest.WordSpec
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
|
||||
//#imports
|
||||
import akka.actor._
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
//#imports
|
||||
|
||||
//#extension
|
||||
class CountExtensionImpl extends Extension {
|
||||
//Since this Extension is a shared instance
|
||||
// per ActorSystem we need to be threadsafe
|
||||
private val counter = new AtomicLong(0)
|
||||
|
||||
//This is the operation this Extension provides
|
||||
def increment() = counter.incrementAndGet()
|
||||
}
|
||||
//#extension
|
||||
|
||||
//#extensionid
|
||||
object CountExtension
|
||||
extends ExtensionId[CountExtensionImpl]
|
||||
with ExtensionIdProvider {
|
||||
//The lookup method is required by ExtensionIdProvider,
|
||||
// so we return ourselves here, this allows us
|
||||
// to configure our extension to be loaded when
|
||||
// the ActorSystem starts up
|
||||
override def lookup = CountExtension
|
||||
|
||||
//This method will be called by Akka
|
||||
// to instantiate our Extension
|
||||
override def createExtension(system: ActorSystemImpl) = new CountExtensionImpl
|
||||
}
|
||||
//#extensionid
|
||||
|
||||
//#extension-usage-actor
|
||||
import akka.actor.Actor
|
||||
|
||||
class MyActor extends Actor {
|
||||
def receive = {
|
||||
case someMessage ⇒
|
||||
CountExtension(context.system).increment()
|
||||
}
|
||||
}
|
||||
//#extension-usage-actor
|
||||
|
||||
//#extension-usage-actor-trait
|
||||
import akka.actor.Actor
|
||||
|
||||
trait Counting { self: Actor ⇒
|
||||
def increment() = CountExtension(context.system).increment()
|
||||
}
|
||||
class MyCounterActor extends Actor with Counting {
|
||||
def receive = {
|
||||
case someMessage ⇒ increment()
|
||||
}
|
||||
}
|
||||
//#extension-usage-actor-trait
|
||||
|
||||
class ExtensionDocSpec extends WordSpec with MustMatchers {
|
||||
|
||||
"demonstrate how to create an extension in Scala" in {
|
||||
val system: ActorSystem = null
|
||||
intercept[Exception] {
|
||||
//#extension-usage
|
||||
CountExtension(system).increment
|
||||
//#extension-usage
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ Dispatchers (Scala)
|
|||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
|
||||
The Dispatcher is an important piece that allows you to configure the right semantics and parameters for optimal performance, throughput and scalability. Different Actors have different needs.
|
||||
|
||||
Akka supports dispatchers for both event-driven lightweight threads, allowing creation of millions of threads on a single workstation, and thread-based Actors, where each dispatcher is bound to a dedicated OS thread.
|
||||
|
|
@ -127,9 +127,9 @@ Work-sharing event-based
|
|||
|
||||
The ``BalancingDispatcher`` is a variation of the ``Dispatcher`` in which Actors of the same type can be set up to
|
||||
share this dispatcher and during execution time the different actors will steal messages from other actors if they
|
||||
have less messages to process.
|
||||
have less messages to process.
|
||||
Although the technique used in this implementation is commonly known as "work stealing", the actual implementation is probably
|
||||
best described as "work donating" because the actor of which work is being stolen takes the initiative.
|
||||
best described as "work donating" because the actor of which work is being stolen takes the initiative.
|
||||
This can be a great way to improve throughput at the cost of a little higher latency.
|
||||
|
||||
.. includecode:: code/akka/docs/dispatcher/DispatcherDocSpec.scala#my-balancing-config
|
||||
|
|
@ -152,8 +152,9 @@ if not specified otherwise.
|
|||
akka {
|
||||
actor {
|
||||
default-dispatcher {
|
||||
task-queue-size = 1000 # If negative (or zero) then an unbounded mailbox is used (default)
|
||||
# If positive then a bounded mailbox is used and the capacity is set to the number specified
|
||||
# If negative (or zero) then an unbounded mailbox is used (default)
|
||||
# If positive then a bounded mailbox is used and the capacity is set to the number specified
|
||||
task-queue-size = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
akka-docs/scala/extending-akka.rst
Normal file
53
akka-docs/scala/extending-akka.rst
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
.. _extending-akka:
|
||||
|
||||
Akka Extensions
|
||||
===============
|
||||
|
||||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
|
||||
Building an Extension
|
||||
---------------------
|
||||
|
||||
So let's create a sample extension that just lets us count the number of times something has happened.
|
||||
|
||||
First, we define what our ``Extension`` should do:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
|
||||
:include: imports,extension
|
||||
|
||||
Then we need to create an ``ExtensionId`` for our extension so we can grab ahold of it.
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
|
||||
:include: imports,extensionid
|
||||
|
||||
Wicked! Now all we need to do is to actually use it:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
|
||||
:include: extension-usage
|
||||
|
||||
Or from inside of an Akka Actor:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
|
||||
:include: extension-usage-actor
|
||||
|
||||
You can also hide extension behind traits:
|
||||
|
||||
.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala
|
||||
:include: extension-usage-actor-trait
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
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``.
|
||||
|
||||
Applicability
|
||||
-------------
|
||||
|
||||
The sky is the limit!
|
||||
By the way, did you know that Akka's ``Typed Actors``, ``Serialization`` and other features are implemented as Akka Extensions?
|
||||
|
|
@ -198,7 +198,7 @@ Then there's a method that's called ``fold`` that takes a start-value, a sequenc
|
|||
.. code-block:: scala
|
||||
|
||||
val futures = for(i <- 1 to 1000) yield Future(i * 2) // Create a sequence of Futures
|
||||
|
||||
|
||||
val futureSum = Future.fold(0)(futures)(_ + _)
|
||||
|
||||
That's all it takes!
|
||||
|
|
@ -244,7 +244,7 @@ In this example, if an ``ArithmeticException`` was thrown while the ``Actor`` pr
|
|||
Timeouts
|
||||
--------
|
||||
|
||||
Waiting forever for a ``Future`` to be completed can be dangerous. It could cause your program to block indefinitly or produce a memory leak. ``Future`` has support for a timeout already builtin with a default of 5 seconds (taken from :ref:`configuration`). A timeout is an instance of ``akka.actor.Timeout`` which contains an ``akka.util.Duration``. A ``Duration`` can be finite, which needs a length and unit type, or infinite. An infinite ``Timeout`` can be dangerous since it will never actually expire.
|
||||
Waiting forever for a ``Future`` to be completed can be dangerous. It could cause your program to block indefinitly or produce a memory leak. ``Future`` has support for a timeout already builtin with a default of 5 seconds (taken from :ref:`configuration`). A timeout is an instance of ``akka.util.Timeout`` which contains an ``akka.util.Duration``. A ``Duration`` can be finite, which needs a length and unit type, or infinite. An infinite ``Timeout`` can be dangerous since it will never actually expire.
|
||||
|
||||
A different ``Timeout`` can be supplied either explicitly or implicitly when a ``Future`` is created. An implicit ``Timeout`` has the benefit of being usable by a for-comprehension as well as being picked up by any methods looking for an implicit ``Timeout``, while an explicit ``Timeout`` can be used in a more controlled manner.
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ Implicit ``Timeout`` example:
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
import akka.actor.Timeout
|
||||
import akka.util.Timeout
|
||||
import akka.util.duration._
|
||||
|
||||
implicit val longTimeout = Timeout(1 minute)
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ Scala API
|
|||
actors
|
||||
typed-actors
|
||||
logging
|
||||
scheduler
|
||||
futures
|
||||
dataflow
|
||||
agents
|
||||
stm
|
||||
transactors
|
||||
fault-tolerance
|
||||
dispatchers
|
||||
routing
|
||||
fsm
|
||||
testing
|
||||
extending-akka
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ For convenience you can mixin the ``log`` member into actors, instead of definin
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
class MyActor extends Actor with akka.actor.ActorLogging {
|
||||
class MyActor extends Actor with akka.actor.ActorLogging {
|
||||
|
||||
The second parameter to the ``Logging`` is the source of this logging channel.
|
||||
The source object is translated to a String according to the following rules:
|
||||
|
|
@ -31,14 +31,14 @@ The source object is translated to a String according to the following rules:
|
|||
* in case of a class an approximation of its simpleName
|
||||
* and in all other cases the simpleName of its class
|
||||
|
||||
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
||||
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
||||
is enabled.
|
||||
|
||||
Event Handler
|
||||
=============
|
||||
|
||||
Logging is performed asynchronously through an event bus. You can configure which event handlers that should
|
||||
subscribe to the logging events. That is done using the 'event-handlers' element in the :ref:`configuration`.
|
||||
Logging is performed asynchronously through an event bus. You can configure which event handlers that should
|
||||
subscribe to the logging events. That is done using the 'event-handlers' element in the :ref:`configuration`.
|
||||
Here you can also define the log level.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
|
@ -46,10 +46,11 @@ Here you can also define the log level.
|
|||
akka {
|
||||
# Event handlers to register at boot time (Logging$DefaultLogger logs to STDOUT)
|
||||
event-handlers = ["akka.event.Logging$DefaultLogger"]
|
||||
loglevel = "DEBUG" # Options: ERROR, WARNING, INFO, DEBUG
|
||||
# Options: ERROR, WARNING, INFO, DEBUG
|
||||
loglevel = "DEBUG"
|
||||
}
|
||||
|
||||
The default one logs to STDOUT and is registered by default. It is not intended to be used for production. There is also an :ref:`slf4j-scala`
|
||||
The default one logs to STDOUT and is registered by default. It is not intended to be used for production. There is also an :ref:`slf4j-scala`
|
||||
event handler available in the 'akka-slf4j' module.
|
||||
|
||||
Example of creating a listener:
|
||||
|
|
@ -63,7 +64,7 @@ Example of creating a listener:
|
|||
SLF4J
|
||||
=====
|
||||
|
||||
Akka provides an event handler for `SL4FJ <http://www.slf4j.org/>`_. This module is available in the 'akka-slf4j.jar'.
|
||||
Akka provides an event handler for `SL4FJ <http://www.slf4j.org/>`_. This module is available in the 'akka-slf4j.jar'.
|
||||
It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4J backend, we recommend `Logback <http://logback.qos.ch/>`_:
|
||||
|
||||
.. code-block:: scala
|
||||
|
|
@ -71,10 +72,10 @@ It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4
|
|||
lazy val logback = "ch.qos.logback" % "logback-classic" % "1.0.0" % "runtime"
|
||||
|
||||
|
||||
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
||||
the :ref:`configuration`. Here you can also define the log level of the event bus.
|
||||
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
||||
the :ref:`configuration`. Here you can also define the log level of the event bus.
|
||||
More fine grained log levels can be defined in the configuration of the SLF4J backend
|
||||
(e.g. logback.xml). The String representation of the source object that is used when
|
||||
(e.g. logback.xml). The String representation of the source object that is used when
|
||||
creating the ``LoggingAdapter`` correspond to the name of the SL4FJ logger.
|
||||
|
||||
.. code-block:: ruby
|
||||
|
|
@ -91,9 +92,9 @@ Since the logging is done asynchronously the thread in which the logging was per
|
|||
Mapped Diagnostic Context (MDC) with attribute name ``sourceThread``.
|
||||
With Logback the thread name is available with ``%X{sourceThread}`` specifier within the pattern layout configuration::
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout>
|
||||
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout>
|
||||
<pattern>%date{ISO8601} %-5level %logger{36} %X{sourceThread} - %msg%n</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
|
|
|
|||
53
akka-docs/scala/scheduler.rst
Normal file
53
akka-docs/scala/scheduler.rst
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
.. _scheduler-scala:
|
||||
|
||||
###################
|
||||
Scheduler (Scala)
|
||||
###################
|
||||
|
||||
Sometimes the need for making things happen in the future arises, and where do you go look then?
|
||||
Look no further than ``ActorSystem``! There you find the :meth:`scheduler` method that returns an instance
|
||||
of akka.actor.Scheduler, this instance is unique per ActorSystem and is used internally for scheduling things
|
||||
to happen at specific points in time. Please note that the scheduled tasks are executed by the default
|
||||
``MessageDispatcher`` of the ``ActorSystem``.
|
||||
|
||||
You can schedule sending of messages to actors and execution of tasks (functions or Runnable).
|
||||
You will get a ``Cancellable`` back that you can call :meth:`cancel` on to cancel the execution of the
|
||||
scheduled operation.
|
||||
|
||||
Some examples
|
||||
-------------
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocSpec.scala
|
||||
:include: imports1,schedule-one-off-message
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocSpec.scala
|
||||
:include: schedule-one-off-thunk
|
||||
|
||||
.. includecode:: code/akka/docs/actor/SchedulerDocSpec.scala
|
||||
:include: schedule-recurring
|
||||
|
||||
From ``akka.actor.ActorSystem``
|
||||
-------------------------------
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/ActorSystem.scala
|
||||
:include: scheduler
|
||||
|
||||
|
||||
The Scheduler interface
|
||||
-----------------------
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: scheduler
|
||||
|
||||
The Cancellable interface
|
||||
-------------------------
|
||||
|
||||
This allows you to ``cancel`` something that has been scheduled for execution.
|
||||
|
||||
.. warning::
|
||||
This does not abort the execution of the task, if it had already been started.
|
||||
|
||||
.. includecode:: ../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: cancellable
|
||||
|
||||
6
akka-docs/scala/transactors.rst
Normal file
6
akka-docs/scala/transactors.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.. _transactors-scala:
|
||||
|
||||
Transactors (Scala)
|
||||
===================
|
||||
|
||||
The Akka Transactors module has not been migrated to Akka 2.0-SNAPSHOT yet.
|
||||
|
|
@ -165,4 +165,4 @@ Here's an example on how you can use traits to mix in behavior in your Typed Act
|
|||
|
||||
.. includecode:: code/TypedActorDocSpec.scala#typed-actor-supercharge
|
||||
|
||||
.. includecode:: code/TypedActorDocSpec.scala#typed-actor-supercharge-usage
|
||||
.. includecode:: code/TypedActorDocSpec.scala#typed-actor-supercharge-usage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue