Actor's in Action with Akka
Actor model
- Make local decisions.
- Send messages to other actors.
- Create new actors.
- Designate the behavior to be used for the next message it receives.
- Fundamental Unit of Computation
The actor
- Force Immutability
- Fundamental communication mechanism
The message
The system
Purpose
- Asynchronous by default
- Immutable states
Concurrency
Akka in scala
Defining the system
The Message
case class User(name: String, surname: String)
- Immutable by default
- Getters automatically defined
- Compliant equals(), hashCode() and toString() implementation
- Compliant serialize()/deserialize()
The Actor
class MyActor extends Actor {
def receive = {
// Matches any string at all
case s: String =>
println(s"You sent me a string: $s")
// Match a more complex case class structure
case user: User =>
println(s"You sent me a user: $user")
// Catch all. Matches any message type
case _ =>
println("Huh?")
}
}
The System
val system = ActorSystem("MyActorSystem")
val system = ActorSystem("MyActorSystem")
val myActor: ActorRef = system.actorOf(Props[MyActor], name = "myActor")
- Props: Configuration class to specify options in the creation of actors
- ActorRef: Untyped reference to an actor. Encapsulates the actor behind a layer of abstraction.
All together now
object App {
def main(args: Array[String]): Unit = {
val system = ActorSystem("MyActorSystem")
val myActor: ActorRef = system.actorOf(Props[MyActor], name = "myActor")
myActor ! User("Borja", "Gorriz")
}
}
class MyActor extends Actor {
def receive = {
// Match a more complex case class structure
case user: User =>
println(s"You sent me a user: $user ")
}
}
case class User(name: String, surname: String)
Sending messages
The tell
myActor ! User("Borja", "Gorriz")
The tell
object App {
def main(args: Array[String]): Unit = {
val system = ActorSystem("MyActorSystem")
val myActor: ActorRef = system.actorOf(Props[MyActor], name = "myActor")
myActor ! User("Borja", "Gorriz")
}
}
class MyActor extends Actor {
def receive = {
// Match a more complex case class structure
case user: User =>
println(s"You sent me a user: $user ")
}
}
case class User(name: String, surname: String)
The ask
myActor ? User("Borja", "Gorriz")
The ask
object App {
def main(args: Array[String]): Unit = {
val system = ActorSystem("MyActorSystem")
val myActor = system.actorOf(Props[MyActor], name = "myActor")
implicit val askTimeout = Timeout(1.second)
(myActor ? User("Borja", "Gorriz")).mapTo[String]
.onSuccess({ case response: String => println(response) })
}
}
class MyActor extends Actor {
def receive = {
case s: String =>
println(s"You sent me a string: $s")
case user: User =>
self ! "just created a user"
sender() ! s"New $user created"
}
}
case class User(name: String, surname: String)
The forward
myActor.forward(User("Borja", "Gorriz"))
object App {
def main(args: Array[String]): Unit = {
val system = ActorSystem("MyActorSystem")
val RootActor = system.actorOf(Props[RootActor], name = "RootActor")
RootActor ! User("Borja", "Gorriz")
}
}
class RootActor() extends Actor {
def receive = {
case user: User =>
val forwardActor = context.actorOf(Props[ForwardActor])
forwardActor ! user
case msg: String => println(s"Result: $msg")
}
}
class ForwardActor() extends Actor {
def receive = {
case user: User =>
val myActor = context.actorOf(Props[MyActor])
myActor.forward(user)
}
}
class MyActor extends Actor {
def receive = {
case user: User =>
sender() ! s"New $user created"
}
}
case class User(name: String, surname: String)
The pipe
pipe(Future) to MyActor
object App {
def main(args: Array[String]): Unit = {
val system = ActorSystem("MyActorSystem")
val pipeActor = system.actorOf(Props[PipeActor], name = "pipeActor")
implicit val askTimeout = Timeout(1.second)
(pipeActor ? User("Borja","Gorriz"))
.mapTo[String].onSuccess({ case response: String => println(response) })
}
}
class MyActor extends Actor {
def receive = {
case user: User =>
sender() ! s"New $user created"
}
}
class PipeActor() extends Actor {
def receive = {
case user: User =>
implicit val askTimeout = Timeout(1.second)
val myActor = context.actorOf(Props[MyActor])
pipe(myActor ? user) to sender()
case _ =>
}
}
case class User(name: String, surname: String)
Patterns & best practices
Boot up
object Boot extends App {
val system = ActorSystem("MyActorSystem")
//now we can just start building actors
}
Actor creation
object DemoActor {
def props(magicNumber: Int): Props = Props(new DemoActor(magicNumber))
}
class DemoActor(magicNumber: Int) extends Actor {
def receive = {
case x: Int => sender() ! (x + magicNumber)
}
}
class SomeOtherActor extends Actor {
context.actorOf(DemoActor.props(42), "demo")
}
tell, don't ask
tell, don't ask
resources
- code examples
- learning akka
- akka docs
- twitter's scala school
- slack groups: #akka , #scala
thank you
akka
By Borja Gorriz Hernando
akka
- 989