278 lines
6.8 KiB
Scala
278 lines
6.8 KiB
Scala
/**
|
|
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
|
|
*/
|
|
package akka.docs.actor
|
|
|
|
//#imports1
|
|
import akka.actor.Actor
|
|
import akka.actor.Props
|
|
import akka.event.Logging
|
|
import akka.dispatch.Future
|
|
|
|
//#imports1
|
|
|
|
//#imports2
|
|
import akka.actor.ActorSystem
|
|
//#imports2
|
|
|
|
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
|
import org.scalatest.matchers.MustMatchers
|
|
import akka.testkit._
|
|
import akka.util._
|
|
import akka.util.duration._
|
|
|
|
//#my-actor
|
|
class MyActor extends Actor {
|
|
val log = Logging(context.system, this)
|
|
def receive = {
|
|
case "test" ⇒ log.info("received test")
|
|
case _ ⇒ log.info("received unknown message")
|
|
}
|
|
}
|
|
//#my-actor
|
|
|
|
case class DoIt(msg: ImmutableMessage)
|
|
case class Message(s: String)
|
|
|
|
//#context-actorOf
|
|
class FirstActor extends Actor {
|
|
val myActor = context.actorOf(Props[MyActor], name = "myactor")
|
|
//#context-actorOf
|
|
//#anonymous-actor
|
|
def receive = {
|
|
case m: DoIt ⇒
|
|
context.actorOf(Props(new Actor {
|
|
def receive = {
|
|
case DoIt(msg) ⇒
|
|
val replyMsg = doSomeDangerousWork(msg)
|
|
sender ! replyMsg
|
|
context.stop(self)
|
|
}
|
|
def doSomeDangerousWork(msg: ImmutableMessage): String = { "done" }
|
|
})) ! m
|
|
|
|
case replyMsg: String ⇒ sender ! replyMsg
|
|
}
|
|
//#anonymous-actor
|
|
}
|
|
|
|
//#system-actorOf
|
|
object Main extends App {
|
|
val system = ActorSystem("MySystem")
|
|
val myActor = system.actorOf(Props[MyActor], name = "myactor")
|
|
//#system-actorOf
|
|
}
|
|
|
|
class ReplyException extends Actor {
|
|
def receive = {
|
|
case _ ⇒
|
|
//#reply-exception
|
|
try {
|
|
val result = operation()
|
|
sender ! result
|
|
} catch {
|
|
case e: Exception ⇒
|
|
sender ! akka.actor.Status.Failure(e)
|
|
throw e
|
|
}
|
|
//#reply-exception
|
|
}
|
|
|
|
def operation(): String = { "Hi" }
|
|
|
|
}
|
|
|
|
//#swapper
|
|
case object Swap
|
|
class Swapper extends Actor {
|
|
import context._
|
|
val log = Logging(system, this)
|
|
|
|
def receive = {
|
|
case Swap ⇒
|
|
log.info("Hi")
|
|
become {
|
|
case Swap ⇒
|
|
log.info("Ho")
|
|
unbecome() // resets the latest 'become' (just for fun)
|
|
}
|
|
}
|
|
}
|
|
|
|
object SwapperApp extends App {
|
|
val system = ActorSystem("SwapperSystem")
|
|
val swap = system.actorOf(Props[Swapper], name = "swapper")
|
|
swap ! Swap // logs Hi
|
|
swap ! Swap // logs Ho
|
|
swap ! Swap // logs Hi
|
|
swap ! Swap // logs Ho
|
|
swap ! Swap // logs Hi
|
|
swap ! Swap // logs Ho
|
|
}
|
|
//#swapper
|
|
|
|
//#receive-orElse
|
|
import akka.actor.Actor.Receive
|
|
|
|
abstract class GenericActor extends Actor {
|
|
// to be defined in subclassing actor
|
|
def specificMessageHandler: Receive
|
|
|
|
// generic message handler
|
|
def genericMessageHandler: Receive = {
|
|
case event ⇒ printf("generic: %s\n", event)
|
|
}
|
|
|
|
def receive = specificMessageHandler orElse genericMessageHandler
|
|
}
|
|
|
|
class SpecificActor extends GenericActor {
|
|
def specificMessageHandler = {
|
|
case event: MyMsg ⇒ printf("specific: %s\n", event.subject)
|
|
}
|
|
}
|
|
|
|
case class MyMsg(subject: String)
|
|
//#receive-orElse
|
|
|
|
class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
|
|
|
"import context" in {
|
|
//#import-context
|
|
class FirstActor extends Actor {
|
|
import context._
|
|
val myActor = actorOf(Props[MyActor], name = "myactor")
|
|
def receive = {
|
|
case x ⇒ myActor ! x
|
|
}
|
|
}
|
|
//#import-context
|
|
|
|
val first = system.actorOf(Props(new FirstActor), name = "first")
|
|
system.stop(first)
|
|
|
|
}
|
|
|
|
"creating actor with AkkaSpec.actorOf" in {
|
|
val myActor = system.actorOf(Props[MyActor])
|
|
|
|
// testing the actor
|
|
|
|
// TODO: convert docs to AkkaSpec(Map(...))
|
|
val filter = EventFilter.custom {
|
|
case e: Logging.Info ⇒ true
|
|
case _ ⇒ false
|
|
}
|
|
system.eventStream.publish(TestEvent.Mute(filter))
|
|
system.eventStream.subscribe(testActor, classOf[Logging.Info])
|
|
|
|
myActor ! "test"
|
|
expectMsgPF(1 second) { case Logging.Info(_, "received test") ⇒ true }
|
|
|
|
myActor ! "unknown"
|
|
expectMsgPF(1 second) { case Logging.Info(_, "received unknown message") ⇒ true }
|
|
|
|
system.eventStream.unsubscribe(testActor)
|
|
system.eventStream.publish(TestEvent.UnMute(filter))
|
|
|
|
system.stop(myActor)
|
|
}
|
|
|
|
"creating actor with constructor" in {
|
|
class MyActor(arg: String) extends Actor {
|
|
def receive = { case _ ⇒ () }
|
|
}
|
|
|
|
//#creating-constructor
|
|
// allows passing in arguments to the MyActor constructor
|
|
val myActor = system.actorOf(Props(new MyActor("...")), name = "myactor")
|
|
//#creating-constructor
|
|
|
|
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
|
|
val dispatcher = system.dispatcherFactory.lookup("my-dispatcher")
|
|
val myActor = system.actorOf(Props[MyActor].withDispatcher(dispatcher), name = "myactor")
|
|
//#creating-props
|
|
|
|
system.stop(myActor)
|
|
}
|
|
|
|
"using ask" in {
|
|
//#using-ask
|
|
class MyActor extends Actor {
|
|
def receive = {
|
|
case x: String ⇒ sender ! x.toUpperCase
|
|
case n: Int ⇒ sender ! (n + 1)
|
|
}
|
|
}
|
|
|
|
val myActor = system.actorOf(Props(new MyActor), name = "myactor")
|
|
implicit val timeout = system.settings.ActorTimeout
|
|
val future = myActor ? "hello"
|
|
for (x ← future) println(x) //Prints "hello"
|
|
|
|
val result: Future[Int] = for (x ← (myActor ? 3).mapTo[Int]) yield { 2 * x }
|
|
//#using-ask
|
|
|
|
system.stop(myActor)
|
|
}
|
|
|
|
"using receiveTimeout" in {
|
|
//#receive-timeout
|
|
import akka.actor.ReceiveTimeout
|
|
import akka.util.duration._
|
|
class MyActor extends Actor {
|
|
context.setReceiveTimeout(30 milliseconds)
|
|
def receive = {
|
|
case "Hello" ⇒ //...
|
|
case ReceiveTimeout ⇒ throw new RuntimeException("received timeout")
|
|
}
|
|
}
|
|
//#receive-timeout
|
|
}
|
|
|
|
"using hot-swap" in {
|
|
//#hot-swap-actor
|
|
class HotSwapActor extends Actor {
|
|
import context._
|
|
def angry: Receive = {
|
|
case "foo" ⇒ sender ! "I am already angry?"
|
|
case "bar" ⇒ become(happy)
|
|
}
|
|
|
|
def happy: Receive = {
|
|
case "bar" ⇒ sender ! "I am already happy :-)"
|
|
case "foo" ⇒ become(angry)
|
|
}
|
|
|
|
def receive = {
|
|
case "foo" ⇒ become(angry)
|
|
case "bar" ⇒ become(happy)
|
|
}
|
|
}
|
|
//#hot-swap-actor
|
|
|
|
val actor = system.actorOf(Props(new HotSwapActor), name = "hot")
|
|
}
|
|
}
|