Merge remote-tracking branch 'origin/master' into wip-2.10.0-RC1-∂π
- currently cheating: uses zeroMQ artifacts for scala 2.10M7 - fixed a bunch of more wrong references to scala.concurrent.util
This commit is contained in:
commit
bff79c2f94
47 changed files with 1036 additions and 287 deletions
|
|
@ -549,13 +549,20 @@ defaults to a 'dead-letter' actor ref.
|
|||
val result = process(request)
|
||||
sender ! result // will have dead-letter actor as default
|
||||
|
||||
Initial receive timeout
|
||||
=======================
|
||||
Receive timeout
|
||||
===============
|
||||
|
||||
A timeout mechanism can be used to receive a message when no initial message is
|
||||
received within a certain time. To receive this timeout you have to set the
|
||||
``receiveTimeout`` property and declare a case handing the ReceiveTimeout
|
||||
object.
|
||||
The `ActorContext` :meth:`setReceiveTimeout` defines the inactivity timeout after which
|
||||
the sending of a `ReceiveTimeout` message is triggered.
|
||||
When specified, the receive function should be able to handle an `akka.actor.ReceiveTimeout` message.
|
||||
1 millisecond is the minimum supported timeout.
|
||||
|
||||
Please note that the receive timeout might fire and enqueue the `ReceiveTimeout` message right after
|
||||
another message was enqueued; hence it is **not guaranteed** that upon reception of the receive
|
||||
timeout there must have been an idle period beforehand as configured via this method.
|
||||
|
||||
Once set, the receive timeout stays in effect (i.e. continues firing repeatedly after inactivity
|
||||
periods). Pass in `Duration.Undefined` to switch off this feature.
|
||||
|
||||
.. includecode:: code/docs/actor/ActorDocSpec.scala#receive-timeout
|
||||
|
||||
|
|
|
|||
|
|
@ -270,10 +270,16 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
|||
import akka.actor.ReceiveTimeout
|
||||
import scala.concurrent.duration._
|
||||
class MyActor extends Actor {
|
||||
// To set an initial delay
|
||||
context.setReceiveTimeout(30 milliseconds)
|
||||
def receive = {
|
||||
case "Hello" ⇒ //...
|
||||
case ReceiveTimeout ⇒ throw new RuntimeException("received timeout")
|
||||
case "Hello" ⇒
|
||||
// To set in a response to a message
|
||||
context.setReceiveTimeout(100 milliseconds)
|
||||
case ReceiveTimeout ⇒
|
||||
// To turn it off
|
||||
context.setReceiveTimeout(Duration.Undefined)
|
||||
throw new RuntimeException("Receive timed out")
|
||||
}
|
||||
}
|
||||
//#receive-timeout
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.pattern
|
||||
|
||||
import language.postfixOps
|
||||
|
||||
import akka.actor.{ Props, ActorRef, Actor }
|
||||
import scala.concurrent.duration._
|
||||
import akka.testkit.{ TimingTest, AkkaSpec, filterException }
|
||||
import docs.pattern.SchedulerPatternSpec.ScheduleInConstructor
|
||||
|
||||
object SchedulerPatternSpec {
|
||||
//#schedule-constructor
|
||||
class ScheduleInConstructor extends Actor {
|
||||
import context.dispatcher
|
||||
val tick =
|
||||
context.system.scheduler.schedule(500 millis, 1000 millis, self, "tick")
|
||||
//#schedule-constructor
|
||||
// this var and constructor is declared here to not show up in the docs
|
||||
var target: ActorRef = null
|
||||
def this(target: ActorRef) = { this(); this.target = target }
|
||||
//#schedule-constructor
|
||||
|
||||
override def postStop() = tick.cancel()
|
||||
|
||||
def receive = {
|
||||
case "tick" ⇒
|
||||
// do something useful here
|
||||
//#schedule-constructor
|
||||
target ! "tick"
|
||||
case "restart" ⇒
|
||||
throw new ArithmeticException
|
||||
//#schedule-constructor
|
||||
}
|
||||
}
|
||||
//#schedule-constructor
|
||||
|
||||
//#schedule-receive
|
||||
class ScheduleInReceive extends Actor {
|
||||
import context._
|
||||
//#schedule-receive
|
||||
// this var and constructor is declared here to not show up in the docs
|
||||
var target: ActorRef = null
|
||||
def this(target: ActorRef) = { this(); this.target = target }
|
||||
//#schedule-receive
|
||||
|
||||
override def preStart() =
|
||||
system.scheduler.scheduleOnce(500 millis, self, "tick")
|
||||
|
||||
// override postRestart so we don't call preStart and schedule a new message
|
||||
override def postRestart(reason: Throwable) = {}
|
||||
|
||||
def receive = {
|
||||
case "tick" ⇒
|
||||
// send another periodic tick after the specified delay
|
||||
system.scheduler.scheduleOnce(1000 millis, self, "tick")
|
||||
// do something useful here
|
||||
//#schedule-receive
|
||||
target ! "tick"
|
||||
case "restart" ⇒
|
||||
throw new ArithmeticException
|
||||
//#schedule-receive
|
||||
}
|
||||
}
|
||||
//#schedule-receive
|
||||
}
|
||||
|
||||
class SchedulerPatternSpec extends AkkaSpec {
|
||||
|
||||
def testSchedule(actor: ActorRef, startDuration: FiniteDuration,
|
||||
afterRestartDuration: FiniteDuration) = {
|
||||
|
||||
filterException[ArithmeticException] {
|
||||
within(startDuration) {
|
||||
expectMsg("tick")
|
||||
expectMsg("tick")
|
||||
expectMsg("tick")
|
||||
}
|
||||
actor ! "restart"
|
||||
within(afterRestartDuration) {
|
||||
expectMsg("tick")
|
||||
expectMsg("tick")
|
||||
}
|
||||
system.stop(actor)
|
||||
}
|
||||
}
|
||||
|
||||
"send periodic ticks from the constructor" taggedAs TimingTest in {
|
||||
testSchedule(system.actorOf(Props(new ScheduleInConstructor(testActor))),
|
||||
3000 millis, 2000 millis)
|
||||
}
|
||||
|
||||
"send ticks from the preStart and receive" taggedAs TimingTest in {
|
||||
testSchedule(system.actorOf(Props(new ScheduleInConstructor(testActor))),
|
||||
3000 millis, 2500 millis)
|
||||
}
|
||||
}
|
||||
|
|
@ -111,6 +111,37 @@ This is where the Spider pattern comes in."
|
|||
|
||||
The pattern is described `Discovering Message Flows in Actor System with the Spider Pattern <http://letitcrash.com/post/30585282971/discovering-message-flows-in-actor-systems-with-the>`_.
|
||||
|
||||
Scheduling Periodic Messages
|
||||
============================
|
||||
|
||||
This pattern describes how to schedule periodic messages to yourself in two different
|
||||
ways.
|
||||
|
||||
The first way is to set up periodic message scheduling in the constructor of the actor,
|
||||
and cancel that scheduled sending in ``postStop`` or else we might have multiple registered
|
||||
message sends to the same actor.
|
||||
|
||||
.. note::
|
||||
|
||||
With this approach the scheduled periodic message send will be restarted with the actor on restarts.
|
||||
This also means that the time period that elapses between two tick messages during a restart may drift
|
||||
off based on when you restart the scheduled message sends relative to the time that the last message was
|
||||
sent, and how long the initial delay is. Worst case scenario is ``interval`` plus ``initialDelay``.
|
||||
|
||||
.. includecode:: code/docs/pattern/SchedulerPatternSpec.scala#schedule-constructor
|
||||
|
||||
The second variant sets up an initial one shot message send in the ``preStart`` method
|
||||
of the actor, and the then the actor when it receives this message sets up a new one shot
|
||||
message send. You also have to override ``postRestart`` so we don't call ``preStart``
|
||||
and schedule the initial message send again.
|
||||
|
||||
.. note::
|
||||
|
||||
With this approach we won't fill up the mailbox with tick messages if the actor is
|
||||
under pressure, but only schedule a new tick message when we have seen the previous one.
|
||||
|
||||
.. includecode:: code/docs/pattern/SchedulerPatternSpec.scala#schedule-receive
|
||||
|
||||
Template Pattern
|
||||
================
|
||||
|
||||
|
|
@ -127,4 +158,3 @@ This is an especially nice pattern, since it does even come with some empty exam
|
|||
Spread the word: this is the easiest way to get famous!
|
||||
|
||||
Please keep this pattern at the end of this file.
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4
|
|||
|
||||
.. code-block:: scala
|
||||
|
||||
lazy val logback = "ch.qos.logback" % "logback-classic" % "1.0.4" % "runtime"
|
||||
lazy val logback = "ch.qos.logback" % "logback-classic" % "1.0.7"
|
||||
|
||||
|
||||
You need to enable the Slf4jEventHandler in the 'event-handlers' element in
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue