Basic introduction into the akka framework.
Declare akka dependency in build.sbt
"com.typesafe.akka" %% "akka-actor" % "2.3.12"
Restart SBT to apply changes.
Actors are living in an actor system
import akka.actor._
object HotelLife extends App {
val system = ActorSystem("hotel-life")
Thread.sleep(5000)
system.shutdown()
}
Create a basic actor
class Concierge extends Actor {
override def receive = {
case _ => println(s"Good morning, Sir. I am $self")
}
}
val jenkins = system.actorOf(Props[Concierge], "jenkins")
An actor lives inside the actor system. It is not accessed directly, instead it is accessed via an ActorRef. An ActorRef provides the method tell
to send the actor a message
jenkins.tell("Good morning", ActorRef.noSender)
The actor is identified by an URL. The URL identifies an actor even across machines. Actors can also be created inside another actor.
class Guest extends Actor {
override def receive = {
case _ => println(s"Nice to meet you. I am $self")
}
}
val bob = context.actorOf(Props[Guest], "bob")
bob.tell("Good morning", self)
Bob is now a child of Jenkins and his URL is a sub path.
An actor can answer to the message sender by sending a message.
sender().tell("Do you have some caviar?", self)
The !
operator allows to send a message without a sender
jenkins.tell("Good morning", ActorRef.noSender) ⇔ jenkins ! "Good morning"
bob.tell("Good morning", self) ⇔ bob ! "Good morning"
Pass an ActorRef to another arctor
class Concierge extends Actor {
override def receive = {
case "Good morning" => {
println("Someone said good morning to me")
sender() ! "Good morning, Sir"
}
}
}
class Guest(concierge: ActorRef) extends Actor {
override def receive = {
case "Go to lobby" => concierge ! "Good morning"
case message => println(s"Oh he said: $message")
}
}
val bob = system.actorOf(Props(new Guest(jenkins)), "bob)
bob ! "Go to lobby"
Sometimes we want to ask an actor for an answer
import akka.pattern.ask
class Guest(concierge: ActorRef) extends Actor {
import ExecutionContext.Implicits.global
implicit val timeout = Timeout(10 seconds)
override def receive = {
case "Go to lobby" => for {
message <- concierge ? "Good morning"
} yield {
println(s"Oh he said: $message")
message
}
}
}