scala.actor is deprecated. Caution: Many articles on the web
are based on scala.actor. Use import akka.actor .
http://docs.scala-lang.org/overviews/core/actors-migration-guide.html
case class Greeting (who: String)
class GreetingActor extends Actor {
def receive = {
case Greeting(who) =>
sender ! (s"Hello, $who! Thanks.")
}
}
val acsy = ActorSystem("WSU-CEG-7370-Actors")
val grtr = acsy . actorOf(Props[GreetingActor], "greeter")
grtr ! Greeting("Brad Pitt")
Props is a configuration class to specify options for the creation of actors.
import akka.actor.{ ActorRef, ActorSystem, Props, Actor }
public class Greeting implements Serializable {
public final String who;
public Greeting(String who) {
this.who = who;
}
}
public class GreetingActor extends UntypedActor {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
public void onReceive(Object message) throws Exception {
if (message instanceof Greeting)
getSender.tell("Hello " + ((Greeting) message).who + " Thanks.");
}
}
ActorSystem acsy = ActorSystem.create("WSU-CEG-7370-Actors");
ActorRef grtr = acsy . actorOf(
new Props(GreetingActor.class), "greeter");
grtr.tell(new Greeting("Brad Pitt"));
case _ => ...
victim ! Kill
context.system.shutdown() the ActorSystem when
everything’s finished
ActorSystem acsy = ActorSystem.create("WSU-CEG-7370-Actors");
receive defines how messages are handled.
! aka tell.
def ! (message: Any)(implicit sender: ActorRef = Actor.noSender)
? sends a message asynchronously and returns a Future
representing a possible reply. Aka ask.
import akka.actor._
class HotSwapActor extends Actor {
import context._
def angry: Receive = {
case "ang" => sender ! "I am already angry >:("
case "hap" => become(happy)
}
def happy: Receive = {
case "hap" => sender ! "I am already happy :-)"
case "ang" => become(angry)
}
def receive = {
case "ang" => become(angry)
case "hap" => become(happy)
}
}
context.become Replaces the current behavior (i.e., the top of the
behavior stack)
context.unbecome pop the stack
import akka.actor.FSM
become, Finite State Machines, and P3
import akka.event.Logging; import akka.actor._
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() // just for fun
}, discardOld = false) /* not replace */ }}
object SwapperApp extends App {
val sys = ActorSystem("SwapperSystem")
val a = sys.actorOf(Props[Swapper], name="swapper")
// alternately logs Hi, Ho, ...
a!Swap; a!Swap; a!Swap; a!Swap; a!Swap; a!Swap
}
restart, stop it, or
escalate the failure up the hierarchy of actors.
Terminated message provided by the
DeathWatch component of the actor system.
import akka.actor.{ Actor, Props, Terminated }
class WatchActor extends Actor {
val child = context.actorOf(Props.empty, "child")
context.watch(child) // registration
var lastSender = system.deadLetters
def receive = {
case "kill" =>
context.stop(child); lastSender = sender()
case Terminated(`child`) =>
lastSender ! "finished"
}
}
Terminated(`child`)
akka.routing strategies:
ExecutionContext is similar to java.util.concurrent. Executor.
import scala.concurrent.ExecutionContext
ExecutionContext interface.
MessageDispatcher, and that
dispatcher doubles as an ExecutionContext.
class PrintActor extends Actor {
def receive = { case x ⇒ println(x) }
}
val printer = system.actorOf(Props[PrintActor])
TimerBasedThrottler
val throttler = system.actorOf( Props(classOf[ TimerBasedThrottler ], 3 msgsPer 1.second)) throttler ! SetTarget(Some(printer)) throttler ! "1"; throttler!"2"; throttler!"3" // These will wait for a second throttler ! "4"; throttler ! "5"
akka.pattern.CircuitBreaker, …
class D extends Actor with ActorLogging {
import context.dispatcher
val breaker = new CircuitBreaker(
context.system.scheduler,
maxFailures = 5, callTimeout = 10.seconds,
resetTimeout = 1.minute). onOpen(notifyMeOnOpen())
def notifyMeOnOpen(): Unit = log.warning(
"My CircuitBreaker is now open, and " +
"will not close for one minute")
system.scheduler().scheduleOnce( Duration.create(50, TimeUnit.MILLISECONDS), testActor, "foo", system.dispatcher(), null )
ExecutionContext
future method which starts an asynchronous computation
and returns a future. The result becomes available once the future
completes.
import scala.concurrent.{ future, promise }
import scala.concurrent.ExecutionContext.Implicits.global
val s = socialNetwork.createSessionFor("user", credentials)
val f: Future[List[Friend]] = future {
s.getFriends() // may take a while
}
success, failure, complete
import scala.concurrent.{ future, promise }
import scala.concurrent.ExecutionContext.Implicits.global
val p = promise[T]
val f = p.future
val prdcr = future { // producer
val r = produceSomething()
p . success . r
continueDoingSomethingUnrelated()
}
val cnsmr = future { // consumer
startDoingSomething()
f . onSuccess {
case r => doSomethingWithResult()
}}
ActorSystem.actorOf method and then …
ActorContext.actorOf.
ActorSystem.actorSelection method
Identify message, to the
actor and use the sender reference of a reply from the actor.
actorFor is deprecated in favor of actorSelection because actor
references acquired with actorFor behave differently for local
and remote actors. Beware: actorOf vs. actorSelection vs. actorFor
context.actorSelection("../*") ! msg
context . actorSelection ("../brother") ! msg
context.actorSelection("/user/serviceA") ! msg
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
...
}
extensions = ["akka.cluster.Cluster"]
cluster {
seed-nodes = [
"akka://ClusterSystem@127.0.0.1:2551",
"akka://ClusterSystem@127.0.0.1:2552"
]
auto-down = on
}
}
What Does "Finished" Mean? The most natural answer to this question appears to be, "When all the Mailboxes are empty." Natural, yes; correct, no. :)
import akka.actor.{Actor, ActorRef, Terminated}
import scala.collection.mutable.ArrayBuffer
object Reaper { case class WatchMe(ref: ActorRef); }
abstract class Reaper extends Actor {
import Reaper._
val watched = ArrayBuffer.empty[ActorRef]
/* Derivations must implement this method. Called
* when everything is dead */
def allSoulsReaped(): Unit
final def receive = {
case WatchMe(ref) =>
context.watch(ref)
watched += ref
case Terminated(ref) =>
watched -= ref
if (watched.isEmpty) allSoulsReaped()
}
}
spray is an open-source toolkit for building
REST/HTTP-based integration layers on top of Scala and Akka. Being
asynchronous, actor-based, fast, lightweight, modular and testable
it's a great way to connect your Scala applications to the world.
ssh to Laptop/OSIS Lab machine 130.108.17.112
% /usr/local/activator-1.1.1/activator ui -Dhttp.address=130.108.17.112 -Dhttp.port=8080 -Dbrowser=/usr/bin/google-chrome
~/.activator/ and ~
// application.conf at the root of the class path.
akka {
loggers = ["akka.event.slf4j.Slf4jLogger"]
loglevel = "DEBUG"
stdout-loglevel = "WARNING"
actor {
provider = "akka.cluster.ClusterActorRefProvider"
default-dispatcher {
# set to 1 for as fair as possible
throughput = 10
}
}
remote { netty.tcp.port = 2552 }
}