SlideShare une entreprise Scribd logo
1  sur  102
Télécharger pour lire hors ligne
Akka Typed
Johan Andrén, Akka Team
Scala Italy, 2018-09-14
Next generation
actors with Akka
Johan Andrén
Akka Team
Stockholm Scala User
Group
@apnylle
markatta.com/codemonkey/
johan.andren@lightbend.com
Build powerful reactive, concurrent,
and distributed applications more
easily
Akka
What are the tools?
Actors – simple & high performance concurrency
Cluster, Cluster tools – tools for building distributed
systems
Streams – reactive streams implementation
Persistence – CQRS + Event Sourcing for Actors
HTTP – fully async streaming HTTP Server
Alpakka – Reactive Streams Integrations a’la Camel
Complete Java & Scala APIs for all features
What are the tools?
Actors – simple & high performance concurrency
Cluster, Cluster tools – tools for building distributed
systems
Streams – reactive streams implementation
Persistence – CQRS + Event Sourcing for Actors
HTTP – fully async streaming HTTP Server
Alpakka – Reactive Streams Integrations a’la Camel
Complete Java & Scala APIs for all features
(already type-safe)
(already type-safe)
(already type-safe)
Typed
Typed
Typed
What problem are we solving?
Actor
Message
Inbox
MessageMessage
actorRef ! message
actorRef.tell(message)
Akka Actor fundamentals
• mutate state (including spawning a child actor)
• send messages to other actors
• change its behavior
Actor
Message
Inbox
MessageMessage
An Actor can…
MVS
(Minimum Viable Sample)
Na-na na-na na-na na-naSample-time!
Also known as “hello world”
At the core of Akka “untyped”
Any => Unit
MyActor extends Actor
On the inside
From the outside
ActorRef
import akka.actor.{Actor, ActorSystem, Props}
object UntypedSample1 extends App {
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
import akka.actor.{Actor, ActorSystem, Props}
object UntypedSample1 extends App {
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
import akka.actor.{Actor, ActorSystem, Props}
object UntypedSample1 extends App {
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
user
my-system
greeter
import akka.actor.{Actor, ActorSystem, Props}
object UntypedSample1 extends App {
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
user
my-system
greeter
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
[info] Running UntypedSample1
Hello Johan!
Hello Scala Italy!
user
greeter
case class Hello(who: String)
class GreetingActor extends Actor {
def receive = {
case Hello(who) => println(s"Hello $who!")
}
}
val props = Props(new GreetingActor)
val system = ActorSystem("my-system")
val ref = system.actorOf(props, "greeter")
ref ! Hello("Johan")
ref ! Hello("Scala Italy")
ref ! "ups"
}
[info] Running UntypedSample1
Hello Johan!
Hello Scala Italy!
user
greeter
At the core of Akka Typed
Msg => Behavior[Msg]
Behavior[Msg]
On the inside
ActorRef[Msg]
From the outside
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
my-system
user (greeter)
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
Behavior[Hello]
ActorSystem[Hello]
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
ActorSystem[Hello]
ActorSystem[Hello]
== ActorRef[Hello]
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
[info] Running TypedSample1
Hello Johan!
Hello Scala Italy!
case class Hello(who: String)
val greetingBehavior: Behavior[Hello] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"Hello $who!")
Behaviors.same
}
val system =
ActorSystem(greetingBehavior, "my-system")
system ! Hello("Johan")
system ! Hello("Scala Italy")
Let’s do another
one right away
The mystery of the changing state
🔎
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
sealed trait Command
case class Hello(who: String) extends Command
case class ChangeGreeting(newGreeting: String)
extends Command
def greeter(greeting: String): Behavior[Command] =
Behaviors.receiveMessage {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeter(newGreeting)
}
val system = ActorSystem(
greeter("Hello"),
"my-system")
system ! Hello("World")
system ! ChangeGreeting("Buon Pomeriggio")
system ! Hello("Scala Italy")
[info] Running TypedSample2
Hello World!
Buon Pomeriggio Scala Italy!
But I don’t like it
(the FP style, that is)
class GreetingBehavior(private var greeting: String)
extends ExtensibleBehavior[Command] {
def receive(
ctx: ActorContext[Command],
msg: Command
): Behavior[Command] = {
msg match {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeting = newGreeting
Behaviors.same
}
}
def receiveSignal(
ctx: ActorContext[Command],
msg: Signal
): Behavior[Command] = {
Behaviors.same
}
}
class GreetingBehavior(private var greeting: String)
extends ExtensibleBehavior[Command] {
def receive(
ctx: ActorContext[Command],
msg: Command
): Behavior[Command] = {
msg match {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeting = newGreeting
Behaviors.same
}
}
def receiveSignal(
ctx: ActorContext[Command],
msg: Signal
): Behavior[Command] = {
Behaviors.same
}
}
class GreetingBehavior(private var greeting: String)
extends ExtensibleBehavior[Command] {
def receive(
ctx: ActorContext[Command],
msg: Command
): Behavior[Command] = {
msg match {
case Hello(who) =>
println(s"$greeting $who!")
Behaviors.same
case ChangeGreeting(newGreeting) =>
greeting = newGreeting
Behaviors.same
}
}
def receiveSignal(
ctx: ActorContext[Command],
msg: Signal
): Behavior[Command] = {
Behaviors.same
}
}
More behavior factories
val behaviorWithSetup: Behavior[Unit] =
Behaviors.setup { ctx =>
ctx.log.info("Starting up")
// other startup logic, for example
// spawn children, subscribe, open resources
// then return the actual behavior used
Behaviors.empty
}
More behavior factories
case class Message(text: String)
val behaviorWithTimer: Behavior[Message] =
Behaviors.withTimers { timers =>
timers.startSingleTimer(
"single",
Message("single"),
1.second)
timers.startPeriodicTimer(
"repeated",
Message("repeated"),
5.seconds)
Behaviors.receive { (ctx, msg) =>
ctx.log.info("Got msg: {}", msg)
Behaviors.same
}
}
More behavior factories
•Behaviors.empty, Behaviors.ignore
•Behaviors.withMDC
•Behaviors.monitor, Behaviors.intercept 

(intercept not in there yet, in progress, so likely)
•Behaviors.receivePartial
•Behaviors.receiveSignal - 

PreRestart, PostStop, Terminated
•Behaviors.supervise
Burglar Alarm
• enabled/disabled with a
pin code
• accepts notifications
about “activity”
• if enabled, on activity,
sound the alarm
“Realistic” Example
DIY
sealed trait AlarmMessage
case object EnableAlarm extends AlarmMessage
case class DisableAlarm(pinCode: String) extends AlarmMessage
case class ActivitySeen(what: String) extends AlarmMessage
def disabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case EnableAlarm =>
enabledAlarm(pinCode)
case _ =>
Behaviors.unhandled
}
}
def disabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case EnableAlarm =>
enabledAlarm(pinCode)
case _ =>
Behaviors.unhandled
}
}
def disabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case EnableAlarm =>
enabledAlarm(pinCode)
case _ =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
def enabledAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.receive { (actorCtx, msg) =>
msg match {
case ActivitySeen(what) =>
actorCtx.log.warning(
"EOEOEOE, activity detected: {}", what)
Behaviors.same
case DisableAlarm(`pinCode`) =>
actorCtx.log.info("Alarm disabled")
disabledAlarm(pinCode)
case DisableAlarm(_) =>
actorCtx.log.warning(
"OEOEOE, unauthorized disable of alarm!")
Behaviors.same
case EnableAlarm =>
Behaviors.unhandled
}
}
val system = ActorSystem(enabledAlarm("0000"), "alarm")
system ! ActivitySeen("door opened")
system ! DisableAlarm("1234")
system ! DisableAlarm("0000")
system ! ActivitySeen("window opened")
system ! EnableAlarm
[WARN] [19:08:45.332] EOEOEOE, activity detected:
door opened
[WARN] [09/13/2018 19:08:45.332] OEOEOE, unauthorized
disable of alarm!
[INFO] [09/13/2018 19:08:45.333] Alarm disabled
• Discoverability, how are things related
• More compile time type-safety, less runtime
debugging

Types helps productivity!
(and results in more reliable systems in
production)
The need for strong/strict typing
“Sending the wrong message to an
actor is actually quite uncommon”
– Myself
• In untyped actors the sender was
auto-magically available - sender()
• In Akka Typed the recipient of
response has to be encoded in
message (why?)
A consequence
RequestForB
ResponseFromB
Request-response with other actors
Actor[ProtocolA] Actor[ProtocolB]
RequestForB
ResponseFromB
A sender() couldn’t
know the type!
Request-response with other actors
ResponseFromB
Response From B is not
part of As protocol
So we can’t use “self”
Actor[ProtocolA] Actor[ProtocolB]
Request-response with other actors
RequestForB(replyTo:
ActorRef[ResponseFromB])
RequestForB(replyTo:
ActorRef[ResponseFromB])
ResponseFromB
?
ResponseFromB => ProtocolA
ProtocolA
Request-response with other actors
Actor[ProtocolA] Actor[ProtocolB]
Request-response with other actors
• One off request-response with a
timeout - ask
• Fire-and-forget with (or “subscribe”)
- adapter
Two flavours:
One off with Ask
sealed trait ProtocolA
case class GotResult(result: String) extends ProtocolA
case class GotNoResult(why: String) extends ProtocolA
// in the actor
implicit val timeout: Timeout = 3.seconds
ctx.ask(actorB)(RequestForB.apply) {
case Success(ResponseFromB(result)) =>
GotResult(result)
case Failure(error) =>
GotNoResult(error.getMessage)
}
Long live the adapter
val adapter: ActorRef[ResponseFromB] =
ctx.messageAdapter {
case ResponseFromB(result) =>
GotResult(result)
}
Behaviors.receiveMessage {
case TriggerRequest =>
actorB ! RequestForB(adapter)
Behaviors.same
}
Distributed Systems
–Leslie Lamport
”A distributed system is one in which
the failure of a computer you didn't
even know existed can render your
own computer unusable”
Why is it so hard?
Reliability: power failure, old network 

equipment, network congestion, coffee in
router, 

rodents, that guy in the IT dept., DDOS attacks…
Latency: loopback vs local net vs shared
congested local net vs internet
Bandwidth: again loopback vs local vs shared
local vs internet
The Joys of Computer Networks:
Partial Failure
✂Node 1 Node 2
request
response
Partial Failure
✂Node 1 Node 2
request💥
Partial Failure
✂Node 1 Node 2
request
💥
Partial Failure
✂Node 1 Node 2
request
respons
💥
Why do it, if it is so hard?
Data or processing doesn’t fit a
single machine

Many objects, that should be kept in memory.
Many not so powerful servers can be cheaper
than a supercomputer.
Elasticity

Being able to scale in (less servers) and out (more
servers) depending on load. Not paying for
servers unless you need them.
Resilience

Building systems that will keep working in the
face of failures or degrade gracefully.
Actor Model vs Network
Interaction already modelled as immutable messages

Data travels over the network in packages, changes has to be explicitly
sent back.
At most once

Data reaches a node on the other side at most once, but can be lost,
already part of model!
A recipient of a message can reply directly to sender

Regardless if there were intermediate recipients of the message:
A > B > C – C can reply directly to A
Messages not limited to request response

Messages can flow in either direction when two systems are connected.
Local
ActorSystem
Message
Message
Actor
Actor
Actor
JVMJVM
Distributed
ActorSystemActorSystem
Message
Message
Actor
Actor
Actor
Akka Cluster + Akka Typed
ActorSystem ActorSystem
ActorSystem
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef[AlarmMessage]
Sensor-Actor
Subscribe(key, actorRef)
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef[AlarmMessage]
Sensor-Actor
Register(Key[AlarmMessage],
ActorRef[AlarmMessage])
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef[AlarmMessage]
Sensor-Actor
Register(Key[AlarmMessage],
ActorRef[AlarmMessage])
Listing(key, actorRefs)
Receptionist
Typed Receptionist
Receptionist
Receptionist
ActorRef[AlarmMessage]
Sensor-Actor
Listing(key, actorRefs)
ActorRef[AlarmMessage]AlarmMessage
Distributed Burglar Alarm
• we can have any number of
nodes
• a sensor on any node can
report activity to the alarm
• The node which the alarm
runs on can change
Example
DYI
Distributed
Sensor-Actor
Sensor-Actor
ActorRef[AlarmMessage]
AlarmMessage
AlarmMessage
Trigger
Trigger
sealed trait AlarmMessage
case object EnableAlarm extends AlarmMessage
case class DisableAlarm(pinCode: String) extends AlarmMessage
case class ActivitySeen(what: String) extends AlarmMessage
val serviceKey = ServiceKey[ActivitySeen]("alarm")
def distributedAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.setup { ctx =>
ctx.log.info("Starting up alarm")
ctx.system.receptionist ! Register(serviceKey, ctx.self)
enabledAlarm(pinCode)
}
Registering an actor providing a service
sealed trait AlarmMessage
case object EnableAlarm extends AlarmMessage
case class DisableAlarm(pinCode: String) extends AlarmMessage
case class ActivitySeen(what: String) extends AlarmMessage
val serviceKey = ServiceKey[ActivitySeen]("alarm")
def distributedAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.setup { ctx =>
ctx.log.info("Starting up alarm")
ctx.system.receptionist ! Register(serviceKey, ctx.self)
enabledAlarm(pinCode)
}
Registering an actor providing a service
sealed trait AlarmMessage
case object EnableAlarm extends AlarmMessage
case class DisableAlarm(pinCode: String) extends AlarmMessage
case class ActivitySeen(what: String) extends AlarmMessage
val serviceKey = ServiceKey[ActivitySeen]("alarm")
def distributedAlarm(pinCode: String): Behavior[AlarmMessage] =
Behaviors.setup { ctx =>
ctx.log.info("Starting up alarm")
ctx.system.receptionist ! Register(serviceKey, ctx.self)
enabledAlarm(pinCode)
}
Registering an actor providing a service
sealed trait SensorMessage
case object Trigger extends SensorMessage
case class AlarmsChanged(
alarms: Set[ActorRef[Alarm.ActivitySeen]]
) extends SensorMessage
def sensor(where: String): Behavior[SensorMessage] =
Behaviors.setup { ctx =>
val adapter = ctx.messageAdapter[Listing] {
case Alarm.serviceKey.Listing(alarms) =>
AlarmsChanged(alarms)
}
val subscribe = Subscribe(Alarm.serviceKey, adapter)
ctx.system.receptionist ! subscribe
sensorWithAlarms(where, Set.empty)
}
Sensor, subscribing to alarms
sealed trait SensorMessage
case object Trigger extends SensorMessage
case class AlarmsChanged(
alarms: Set[ActorRef[Alarm.ActivitySeen]]
) extends SensorMessage
def sensor(where: String): Behavior[SensorMessage] =
Behaviors.setup { ctx =>
val adapter = ctx.messageAdapter[Listing] {
case Alarm.serviceKey.Listing(alarms) =>
AlarmsChanged(alarms)
}
val subscribe = Subscribe(Alarm.serviceKey, adapter)
ctx.system.receptionist ! subscribe
sensorWithAlarms(where, Set.empty)
}
Sensor, subscribing to alarms
sealed trait SensorMessage
case object Trigger extends SensorMessage
case class AlarmsChanged(
alarms: Set[ActorRef[Alarm.ActivitySeen]]
) extends SensorMessage
def sensor(where: String): Behavior[SensorMessage] =
Behaviors.setup { ctx =>
val adapter = ctx.messageAdapter[Listing] {
case Alarm.serviceKey.Listing(alarms) =>
AlarmsChanged(alarms)
}
val subscribe = Subscribe(Alarm.serviceKey, adapter)
ctx.system.receptionist ! subscribe
sensorWithAlarms(where, Set.empty)
}
Sensor, subscribing to alarms
sealed trait SensorMessage
case object Trigger extends SensorMessage
case class AlarmsChanged(
alarms: Set[ActorRef[Alarm.ActivitySeen]]
) extends SensorMessage
def sensor(where: String): Behavior[SensorMessage] =
Behaviors.setup { ctx =>
val adapter = ctx.messageAdapter[Listing] {
case Alarm.serviceKey.Listing(alarms) =>
AlarmsChanged(alarms)
}
val subscribe = Subscribe(Alarm.serviceKey, adapter)
ctx.system.receptionist ! subscribe
sensorWithAlarms(where, Set.empty)
}
Sensor, subscribing to alarms
sealed trait SensorMessage
case object Trigger extends SensorMessage
case class AlarmsChanged(
alarms: Set[ActorRef[Alarm.ActivitySeen]]
) extends SensorMessage
def sensor(where: String): Behavior[SensorMessage] =
Behaviors.setup { ctx =>
val adapter = ctx.messageAdapter[Listing] {
case Alarm.serviceKey.Listing(alarms) =>
AlarmsChanged(alarms)
}
val subscribe = Subscribe(Alarm.serviceKey, adapter)
ctx.system.receptionist ! subscribe
sensorWithAlarms(where, Set.empty)
}
Sensor, subscribing to alarms
def sensorWithAlarms(
where: String,
alarms: Set[ActorRef[Alarm.ActivitySeen]]
): Behavior[SensorMessage] =
Behaviors.receive { (ctx, msg) =>
msg match {
case Trigger =>
val event = Alarm.ActivitySeen(where)
alarms.foreach(_ ! event)
Behaviors.same
case Sensor.AlarmsChanged(newSetOfAlarms) =>
ctx.log.info(s"New set of alarms: {}",
newSetOfAlarms)
sensorWithAlarms(where, newSetOfAlarms)
}
}
Sensor, react to alarm changes
def sensorWithAlarms(
where: String,
alarms: Set[ActorRef[Alarm.ActivitySeen]]
): Behavior[SensorMessage] =
Behaviors.receive { (ctx, msg) =>
msg match {
case Trigger =>
val event = Alarm.ActivitySeen(where)
alarms.foreach(_ ! event)
Behaviors.same
case Sensor.AlarmsChanged(newSetOfAlarms) =>
ctx.log.info(s"New set of alarms: {}",
newSetOfAlarms)
sensorWithAlarms(where, newSetOfAlarms)
}
}
Sensor, react to alarm changes
def sensorWithAlarms(
where: String,
alarms: Set[ActorRef[Alarm.ActivitySeen]]
): Behavior[SensorMessage] =
Behaviors.receive { (ctx, msg) =>
msg match {
case Trigger =>
val event = Alarm.ActivitySeen(where)
alarms.foreach(_ ! event)
Behaviors.same
case Sensor.AlarmsChanged(newSetOfAlarms) =>
ctx.log.info(s"New set of alarms: {}",
newSetOfAlarms)
sensorWithAlarms(where, newSetOfAlarms)
}
}
Sensor, react to alarm changes
def sensorWithAlarms(
where: String,
alarms: Set[ActorRef[Alarm.ActivitySeen]]
): Behavior[SensorMessage] =
Behaviors.receive { (ctx, msg) =>
msg match {
case Trigger =>
val event = Alarm.ActivitySeen(where)
alarms.foreach(_ ! event)
Behaviors.same
case Sensor.AlarmsChanged(newSetOfAlarms) =>
ctx.log.info(s"New set of alarms: {}",
newSetOfAlarms)
sensorWithAlarms(where, newSetOfAlarms)
}
}
Sensor, react to alarm changes
Cluster config
val config = ConfigFactory.parseString(
"""
akka.actor.provider=cluster
akka.remote.artery.enabled=true
akka.remote.artery.transport=tcp
# get a port from the OS
akka.remote.artery.canonical.port=0
akka.remote.artery.canonical.host=127.0.0.1
# these are ok just because this is a sample
akka.cluster.jmx.multi-mbeans-in-same-jvm=on
akka.actor.warn-about-java-serializer-usage=off
""")
Programmatic cluster startup
val system1 = ActorSystem(
distributedAlarm(pinCode = "0000"), "alarm", config)
val system2 = ActorSystem(sensor("window"), "alarm", config)
val system3 = ActorSystem(sensor("door"), "alarm", config)
// Note: in a real system you would not likely
// run multiple nodes in the same JVM
val node1 = Cluster(system1)
val node2 = Cluster(system2)
val node3 = Cluster(system3)
// node 1 joins itself to form cluster
node1.manager ! Join(node1.selfMember.address)
// the other two joins that cluster
node2.manager ! Join(node1.selfMember.address)
node3.manager ! Join(node1.selfMember.address)
Programmatic cluster startup
val system1 = ActorSystem(
distributedAlarm(pinCode = "0000"), "alarm", config)
val system2 = ActorSystem(sensor("window"), "alarm", config)
val system3 = ActorSystem(sensor("door"), "alarm", config)
// Note: in a real system you would not likely
// run multiple nodes in the same JVM
val node1 = Cluster(system1)
val node2 = Cluster(system2)
val node3 = Cluster(system3)
// node 1 joins itself to form cluster
node1.manager ! Join(node1.selfMember.address)
// the other two joins that cluster
node2.manager ! Join(node1.selfMember.address)
node3.manager ! Join(node1.selfMember.address)
Programmatic cluster startup
val system1 = ActorSystem(
distributedAlarm(pinCode = "0000"), "alarm", config)
val system2 = ActorSystem(sensor("window"), "alarm", config)
val system3 = ActorSystem(sensor("door"), "alarm", config)
// Note: in a real system you would not likely
// run multiple nodes in the same JVM
val node1 = Cluster(system1)
val node2 = Cluster(system2)
val node3 = Cluster(system3)
// node 1 joins itself to form cluster
node1.manager ! Join(node1.selfMember.address)
// the other two joins that cluster
node2.manager ! Join(node1.selfMember.address)
node3.manager ! Join(node1.selfMember.address)
Simulate some activity
// at some point in time
system2 ! Sensor.Trigger
system3 ! Sensor.Trigger
…
[INFO] [17:48:27.456] New set of alarms: Set(Actor[akka://
alarm-system@127.0.0.1:54960/user#0])
[INFO] [17:48:27.511] New set of alarms: Set(Actor[akka://
alarm-system@127.0.0.1:54960/user#0])
[WARN] [17:48:29.021] EOEOEOE, activity detected: window
[WARN] [17:48:31.011] EOEOEOE, activity detected: door
Summary
• On message - message another actor,
change state or behavior
• Types gives better guardrails and makes
understanding the system easier
• We can use the same abstraction for
local and distributed
How ready is it?
• APIs not frozen (normally we keep binary
compatibility in minor releases) - we expect
only minor changes though
• Pretty much the same since mid spring 2018
• Most likely to change - Typed Persistence
• All cluster APIs and Cluster tools covered
• Working towards a GA, hopefully this fall
GitHub repo with all samples in this talk
https://git.io/fAiZt
Akka typed docs
doc.akka.io/docs/akka/current/typed
More resources
blog.akka.io - news and articles
discuss.akka.io - forums
developer.lightbend.com - samples
Further reading
Questions?
GitHub repo with all samples in this talk
https://git.io/fAiZt
http://akka.io
@apnylle
johan.andren@lightbend.com
Thanks for listening!

Contenu connexe

Tendances

Akka streams - Umeå java usergroup
Akka streams - Umeå java usergroupAkka streams - Umeå java usergroup
Akka streams - Umeå java usergroupJohan Andrén
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentationGene Chang
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsKonrad Malawski
 
Building reactive distributed systems with Akka
Building reactive distributed systems with Akka Building reactive distributed systems with Akka
Building reactive distributed systems with Akka Johan Andrén
 
Async - react, don't wait - PingConf
Async - react, don't wait - PingConfAsync - react, don't wait - PingConf
Async - react, don't wait - PingConfJohan Andrén
 
Scala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streamsScala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streamsJohan Andrén
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Konrad Malawski
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterKonstantin Tsykulenko
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka StreamsKonrad Malawski
 
A dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioA dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioGioia Ballin
 
HBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceHBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceKonrad Malawski
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesKonrad Malawski
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Jiayun Zhou
 
VJUG24 - Reactive Integrations with Akka Streams
VJUG24  - Reactive Integrations with Akka StreamsVJUG24  - Reactive Integrations with Akka Streams
VJUG24 - Reactive Integrations with Akka StreamsJohan Andrén
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matterSkills Matter
 
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Konrad Malawski
 
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...Tim Chaplin
 
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...Codemotion
 
Resilient Applications with Akka Persistence - Scaladays 2014
Resilient Applications with Akka Persistence - Scaladays 2014Resilient Applications with Akka Persistence - Scaladays 2014
Resilient Applications with Akka Persistence - Scaladays 2014Björn Antonsson
 

Tendances (20)

Akka streams - Umeå java usergroup
Akka streams - Umeå java usergroupAkka streams - Umeå java usergroup
Akka streams - Umeå java usergroup
 
Akka Actor presentation
Akka Actor presentationAkka Actor presentation
Akka Actor presentation
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
 
Building reactive distributed systems with Akka
Building reactive distributed systems with Akka Building reactive distributed systems with Akka
Building reactive distributed systems with Akka
 
Async - react, don't wait - PingConf
Async - react, don't wait - PingConfAsync - react, don't wait - PingConf
Async - react, don't wait - PingConf
 
Scala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streamsScala usergroup stockholm - reactive integrations with akka streams
Scala usergroup stockholm - reactive integrations with akka streams
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
 
Developing distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka ClusterDeveloping distributed applications with Akka and Akka Cluster
Developing distributed applications with Akka and Akka Cluster
 
Reactive integrations with Akka Streams
Reactive integrations with Akka StreamsReactive integrations with Akka Streams
Reactive integrations with Akka Streams
 
A dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioA dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenario
 
HBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceHBase RowKey design for Akka Persistence
HBase RowKey design for Akka Persistence
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutes
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
 
VJUG24 - Reactive Integrations with Akka Streams
VJUG24  - Reactive Integrations with Akka StreamsVJUG24  - Reactive Integrations with Akka Streams
VJUG24 - Reactive Integrations with Akka Streams
 
Akka lsug skills matter
Akka lsug skills matterAkka lsug skills matter
Akka lsug skills matter
 
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018Networks and Types - the Future of Akka @ ScalaDays NYC 2018
Networks and Types - the Future of Akka @ ScalaDays NYC 2018
 
Concurrecny inf sharp
Concurrecny inf sharpConcurrecny inf sharp
Concurrecny inf sharp
 
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
 
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
 
Resilient Applications with Akka Persistence - Scaladays 2014
Resilient Applications with Akka Persistence - Scaladays 2014Resilient Applications with Akka Persistence - Scaladays 2014
Resilient Applications with Akka Persistence - Scaladays 2014
 

Similaire à Akka Typed Actors with Behavior and State Changes

Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akkaBardia Heydari
 
Testing akka-actors
Testing akka-actorsTesting akka-actors
Testing akka-actorsKnoldus Inc.
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsAndrii Lashchenko
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Functional Thinking - Programming with Lambdas in Java 8
Functional Thinking - Programming with Lambdas in Java 8Functional Thinking - Programming with Lambdas in Java 8
Functional Thinking - Programming with Lambdas in Java 8Ganesh Samarthyam
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupHenrik Engström
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Queryitsarsalan
 
Building Stateful Microservices With Akka
Building Stateful Microservices With AkkaBuilding Stateful Microservices With Akka
Building Stateful Microservices With AkkaYaroslav Tkachenko
 
Back to the futures, actors and pipes: using Akka for large-scale data migration
Back to the futures, actors and pipes: using Akka for large-scale data migrationBack to the futures, actors and pipes: using Akka for large-scale data migration
Back to the futures, actors and pipes: using Akka for large-scale data migrationManuel Bernhardt
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Ganesh Samarthyam
 

Similaire à Akka Typed Actors with Behavior and State Changes (20)

Concurrency and scalability with akka
Concurrency and scalability  with akkaConcurrency and scalability  with akka
Concurrency and scalability with akka
 
Lambda Functions in Java 8
Lambda Functions in Java 8Lambda Functions in Java 8
Lambda Functions in Java 8
 
Testing akka-actors
Testing akka-actorsTesting akka-actors
Testing akka-actors
 
Message-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applicationsMessage-based communication patterns in distributed Akka applications
Message-based communication patterns in distributed Akka applications
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Functional Thinking - Programming with Lambdas in Java 8
Functional Thinking - Programming with Lambdas in Java 8Functional Thinking - Programming with Lambdas in Java 8
Functional Thinking - Programming with Lambdas in Java 8
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetup
 
Akka introtalk HyScala DEC 2016
Akka introtalk HyScala DEC 2016Akka introtalk HyScala DEC 2016
Akka introtalk HyScala DEC 2016
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Query
 
Introduction to-scala
Introduction to-scalaIntroduction to-scala
Introduction to-scala
 
Building Stateful Microservices With Akka
Building Stateful Microservices With AkkaBuilding Stateful Microservices With Akka
Building Stateful Microservices With Akka
 
Back to the futures, actors and pipes: using Akka for large-scale data migration
Back to the futures, actors and pipes: using Akka for large-scale data migrationBack to the futures, actors and pipes: using Akka for large-scale data migration
Back to the futures, actors and pipes: using Akka for large-scale data migration
 
Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams Productive Programming in Java 8 - with Lambdas and Streams
Productive Programming in Java 8 - with Lambdas and Streams
 
Akka 2.0 Reloaded
Akka 2.0 ReloadedAkka 2.0 Reloaded
Akka 2.0 Reloaded
 
Akka knolx
Akka knolxAkka knolx
Akka knolx
 
Introducing Akka
Introducing AkkaIntroducing Akka
Introducing Akka
 

Plus de Johan Andrén

Asynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsAsynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsJohan Andrén
 
Introduction to akka actors with java 8
Introduction to akka actors with java 8Introduction to akka actors with java 8
Introduction to akka actors with java 8Johan Andrén
 
Scala frukostseminarium
Scala frukostseminariumScala frukostseminarium
Scala frukostseminariumJohan Andrén
 
Introduction to Akka
Introduction to AkkaIntroduction to Akka
Introduction to AkkaJohan Andrén
 
Async – react, don't wait
Async – react, don't waitAsync – react, don't wait
Async – react, don't waitJohan Andrén
 
Akka frukostseminarium
Akka   frukostseminariumAkka   frukostseminarium
Akka frukostseminariumJohan Andrén
 
Macros and reflection in scala 2.10
Macros and reflection in scala 2.10Macros and reflection in scala 2.10
Macros and reflection in scala 2.10Johan Andrén
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to ScalaJohan Andrén
 

Plus de Johan Andrén (9)

Asynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsAsynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka Streams
 
Introduction to akka actors with java 8
Introduction to akka actors with java 8Introduction to akka actors with java 8
Introduction to akka actors with java 8
 
Scala frukostseminarium
Scala frukostseminariumScala frukostseminarium
Scala frukostseminarium
 
Introduction to Akka
Introduction to AkkaIntroduction to Akka
Introduction to Akka
 
Async – react, don't wait
Async – react, don't waitAsync – react, don't wait
Async – react, don't wait
 
Akka frukostseminarium
Akka   frukostseminariumAkka   frukostseminarium
Akka frukostseminarium
 
Macros and reflection in scala 2.10
Macros and reflection in scala 2.10Macros and reflection in scala 2.10
Macros and reflection in scala 2.10
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Duchess scala-2012
Duchess scala-2012Duchess scala-2012
Duchess scala-2012
 

Dernier

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 

Dernier (20)

DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 

Akka Typed Actors with Behavior and State Changes

  • 1. Akka Typed Johan Andrén, Akka Team Scala Italy, 2018-09-14 Next generation actors with Akka
  • 2. Johan Andrén Akka Team Stockholm Scala User Group @apnylle markatta.com/codemonkey/ johan.andren@lightbend.com
  • 3. Build powerful reactive, concurrent, and distributed applications more easily Akka
  • 4. What are the tools? Actors – simple & high performance concurrency Cluster, Cluster tools – tools for building distributed systems Streams – reactive streams implementation Persistence – CQRS + Event Sourcing for Actors HTTP – fully async streaming HTTP Server Alpakka – Reactive Streams Integrations a’la Camel Complete Java & Scala APIs for all features
  • 5. What are the tools? Actors – simple & high performance concurrency Cluster, Cluster tools – tools for building distributed systems Streams – reactive streams implementation Persistence – CQRS + Event Sourcing for Actors HTTP – fully async streaming HTTP Server Alpakka – Reactive Streams Integrations a’la Camel Complete Java & Scala APIs for all features (already type-safe) (already type-safe) (already type-safe) Typed Typed Typed
  • 6. What problem are we solving?
  • 8. • mutate state (including spawning a child actor) • send messages to other actors • change its behavior Actor Message Inbox MessageMessage An Actor can…
  • 9. MVS (Minimum Viable Sample) Na-na na-na na-na na-naSample-time! Also known as “hello world”
  • 10. At the core of Akka “untyped” Any => Unit MyActor extends Actor On the inside From the outside ActorRef
  • 11. import akka.actor.{Actor, ActorSystem, Props} object UntypedSample1 extends App { case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" }
  • 12. import akka.actor.{Actor, ActorSystem, Props} object UntypedSample1 extends App { case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" }
  • 13. import akka.actor.{Actor, ActorSystem, Props} object UntypedSample1 extends App { case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" } user my-system greeter
  • 14. import akka.actor.{Actor, ActorSystem, Props} object UntypedSample1 extends App { case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" } user my-system greeter
  • 15. case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" } [info] Running UntypedSample1 Hello Johan! Hello Scala Italy! user greeter
  • 16. case class Hello(who: String) class GreetingActor extends Actor { def receive = { case Hello(who) => println(s"Hello $who!") } } val props = Props(new GreetingActor) val system = ActorSystem("my-system") val ref = system.actorOf(props, "greeter") ref ! Hello("Johan") ref ! Hello("Scala Italy") ref ! "ups" } [info] Running UntypedSample1 Hello Johan! Hello Scala Italy! user greeter
  • 17. At the core of Akka Typed Msg => Behavior[Msg] Behavior[Msg] On the inside ActorRef[Msg] From the outside
  • 18. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy")
  • 19. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy")
  • 20. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy")
  • 21. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy") my-system user (greeter)
  • 22. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy") Behavior[Hello] ActorSystem[Hello]
  • 23. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy") ActorSystem[Hello] ActorSystem[Hello] == ActorRef[Hello]
  • 24. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy")
  • 25. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy") [info] Running TypedSample1 Hello Johan! Hello Scala Italy!
  • 26. case class Hello(who: String) val greetingBehavior: Behavior[Hello] = Behaviors.receiveMessage { case Hello(who) => println(s"Hello $who!") Behaviors.same } val system = ActorSystem(greetingBehavior, "my-system") system ! Hello("Johan") system ! Hello("Scala Italy")
  • 27. Let’s do another one right away The mystery of the changing state 🔎
  • 28. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 29. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 30. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 31. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 32. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 33. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 34. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy")
  • 35. sealed trait Command case class Hello(who: String) extends Command case class ChangeGreeting(newGreeting: String) extends Command def greeter(greeting: String): Behavior[Command] = Behaviors.receiveMessage { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeter(newGreeting) } val system = ActorSystem( greeter("Hello"), "my-system") system ! Hello("World") system ! ChangeGreeting("Buon Pomeriggio") system ! Hello("Scala Italy") [info] Running TypedSample2 Hello World! Buon Pomeriggio Scala Italy!
  • 36. But I don’t like it (the FP style, that is)
  • 37. class GreetingBehavior(private var greeting: String) extends ExtensibleBehavior[Command] { def receive( ctx: ActorContext[Command], msg: Command ): Behavior[Command] = { msg match { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeting = newGreeting Behaviors.same } } def receiveSignal( ctx: ActorContext[Command], msg: Signal ): Behavior[Command] = { Behaviors.same } }
  • 38. class GreetingBehavior(private var greeting: String) extends ExtensibleBehavior[Command] { def receive( ctx: ActorContext[Command], msg: Command ): Behavior[Command] = { msg match { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeting = newGreeting Behaviors.same } } def receiveSignal( ctx: ActorContext[Command], msg: Signal ): Behavior[Command] = { Behaviors.same } }
  • 39. class GreetingBehavior(private var greeting: String) extends ExtensibleBehavior[Command] { def receive( ctx: ActorContext[Command], msg: Command ): Behavior[Command] = { msg match { case Hello(who) => println(s"$greeting $who!") Behaviors.same case ChangeGreeting(newGreeting) => greeting = newGreeting Behaviors.same } } def receiveSignal( ctx: ActorContext[Command], msg: Signal ): Behavior[Command] = { Behaviors.same } }
  • 40. More behavior factories val behaviorWithSetup: Behavior[Unit] = Behaviors.setup { ctx => ctx.log.info("Starting up") // other startup logic, for example // spawn children, subscribe, open resources // then return the actual behavior used Behaviors.empty }
  • 41. More behavior factories case class Message(text: String) val behaviorWithTimer: Behavior[Message] = Behaviors.withTimers { timers => timers.startSingleTimer( "single", Message("single"), 1.second) timers.startPeriodicTimer( "repeated", Message("repeated"), 5.seconds) Behaviors.receive { (ctx, msg) => ctx.log.info("Got msg: {}", msg) Behaviors.same } }
  • 42. More behavior factories •Behaviors.empty, Behaviors.ignore •Behaviors.withMDC •Behaviors.monitor, Behaviors.intercept 
 (intercept not in there yet, in progress, so likely) •Behaviors.receivePartial •Behaviors.receiveSignal - 
 PreRestart, PostStop, Terminated •Behaviors.supervise
  • 43. Burglar Alarm • enabled/disabled with a pin code • accepts notifications about “activity” • if enabled, on activity, sound the alarm “Realistic” Example DIY
  • 44. sealed trait AlarmMessage case object EnableAlarm extends AlarmMessage case class DisableAlarm(pinCode: String) extends AlarmMessage case class ActivitySeen(what: String) extends AlarmMessage
  • 45. def disabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case EnableAlarm => enabledAlarm(pinCode) case _ => Behaviors.unhandled } }
  • 46. def disabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case EnableAlarm => enabledAlarm(pinCode) case _ => Behaviors.unhandled } }
  • 47. def disabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case EnableAlarm => enabledAlarm(pinCode) case _ => Behaviors.unhandled } }
  • 48. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 49. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 50. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 51. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 52. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 53. def enabledAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.receive { (actorCtx, msg) => msg match { case ActivitySeen(what) => actorCtx.log.warning( "EOEOEOE, activity detected: {}", what) Behaviors.same case DisableAlarm(`pinCode`) => actorCtx.log.info("Alarm disabled") disabledAlarm(pinCode) case DisableAlarm(_) => actorCtx.log.warning( "OEOEOE, unauthorized disable of alarm!") Behaviors.same case EnableAlarm => Behaviors.unhandled } }
  • 54. val system = ActorSystem(enabledAlarm("0000"), "alarm") system ! ActivitySeen("door opened") system ! DisableAlarm("1234") system ! DisableAlarm("0000") system ! ActivitySeen("window opened") system ! EnableAlarm [WARN] [19:08:45.332] EOEOEOE, activity detected: door opened [WARN] [09/13/2018 19:08:45.332] OEOEOE, unauthorized disable of alarm! [INFO] [09/13/2018 19:08:45.333] Alarm disabled
  • 55. • Discoverability, how are things related • More compile time type-safety, less runtime debugging
 Types helps productivity! (and results in more reliable systems in production) The need for strong/strict typing “Sending the wrong message to an actor is actually quite uncommon” – Myself
  • 56. • In untyped actors the sender was auto-magically available - sender() • In Akka Typed the recipient of response has to be encoded in message (why?) A consequence
  • 58. Actor[ProtocolA] Actor[ProtocolB] RequestForB ResponseFromB A sender() couldn’t know the type! Request-response with other actors
  • 59. ResponseFromB Response From B is not part of As protocol So we can’t use “self” Actor[ProtocolA] Actor[ProtocolB] Request-response with other actors RequestForB(replyTo: ActorRef[ResponseFromB])
  • 61. Request-response with other actors • One off request-response with a timeout - ask • Fire-and-forget with (or “subscribe”) - adapter Two flavours:
  • 62. One off with Ask sealed trait ProtocolA case class GotResult(result: String) extends ProtocolA case class GotNoResult(why: String) extends ProtocolA // in the actor implicit val timeout: Timeout = 3.seconds ctx.ask(actorB)(RequestForB.apply) { case Success(ResponseFromB(result)) => GotResult(result) case Failure(error) => GotNoResult(error.getMessage) }
  • 63. Long live the adapter val adapter: ActorRef[ResponseFromB] = ctx.messageAdapter { case ResponseFromB(result) => GotResult(result) } Behaviors.receiveMessage { case TriggerRequest => actorB ! RequestForB(adapter) Behaviors.same }
  • 64. Distributed Systems –Leslie Lamport ”A distributed system is one in which the failure of a computer you didn't even know existed can render your own computer unusable”
  • 65. Why is it so hard? Reliability: power failure, old network 
 equipment, network congestion, coffee in router, 
 rodents, that guy in the IT dept., DDOS attacks… Latency: loopback vs local net vs shared congested local net vs internet Bandwidth: again loopback vs local vs shared local vs internet The Joys of Computer Networks:
  • 66. Partial Failure ✂Node 1 Node 2 request response
  • 67. Partial Failure ✂Node 1 Node 2 request💥
  • 68. Partial Failure ✂Node 1 Node 2 request 💥
  • 69. Partial Failure ✂Node 1 Node 2 request respons 💥
  • 70. Why do it, if it is so hard? Data or processing doesn’t fit a single machine
 Many objects, that should be kept in memory. Many not so powerful servers can be cheaper than a supercomputer. Elasticity
 Being able to scale in (less servers) and out (more servers) depending on load. Not paying for servers unless you need them. Resilience
 Building systems that will keep working in the face of failures or degrade gracefully.
  • 71. Actor Model vs Network Interaction already modelled as immutable messages
 Data travels over the network in packages, changes has to be explicitly sent back. At most once
 Data reaches a node on the other side at most once, but can be lost, already part of model! A recipient of a message can reply directly to sender
 Regardless if there were intermediate recipients of the message: A > B > C – C can reply directly to A Messages not limited to request response
 Messages can flow in either direction when two systems are connected.
  • 74. Akka Cluster + Akka Typed ActorSystem ActorSystem ActorSystem
  • 79. Distributed Burglar Alarm • we can have any number of nodes • a sensor on any node can report activity to the alarm • The node which the alarm runs on can change Example DYI Distributed
  • 81. sealed trait AlarmMessage case object EnableAlarm extends AlarmMessage case class DisableAlarm(pinCode: String) extends AlarmMessage case class ActivitySeen(what: String) extends AlarmMessage val serviceKey = ServiceKey[ActivitySeen]("alarm") def distributedAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.setup { ctx => ctx.log.info("Starting up alarm") ctx.system.receptionist ! Register(serviceKey, ctx.self) enabledAlarm(pinCode) } Registering an actor providing a service
  • 82. sealed trait AlarmMessage case object EnableAlarm extends AlarmMessage case class DisableAlarm(pinCode: String) extends AlarmMessage case class ActivitySeen(what: String) extends AlarmMessage val serviceKey = ServiceKey[ActivitySeen]("alarm") def distributedAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.setup { ctx => ctx.log.info("Starting up alarm") ctx.system.receptionist ! Register(serviceKey, ctx.self) enabledAlarm(pinCode) } Registering an actor providing a service
  • 83. sealed trait AlarmMessage case object EnableAlarm extends AlarmMessage case class DisableAlarm(pinCode: String) extends AlarmMessage case class ActivitySeen(what: String) extends AlarmMessage val serviceKey = ServiceKey[ActivitySeen]("alarm") def distributedAlarm(pinCode: String): Behavior[AlarmMessage] = Behaviors.setup { ctx => ctx.log.info("Starting up alarm") ctx.system.receptionist ! Register(serviceKey, ctx.self) enabledAlarm(pinCode) } Registering an actor providing a service
  • 84. sealed trait SensorMessage case object Trigger extends SensorMessage case class AlarmsChanged( alarms: Set[ActorRef[Alarm.ActivitySeen]] ) extends SensorMessage def sensor(where: String): Behavior[SensorMessage] = Behaviors.setup { ctx => val adapter = ctx.messageAdapter[Listing] { case Alarm.serviceKey.Listing(alarms) => AlarmsChanged(alarms) } val subscribe = Subscribe(Alarm.serviceKey, adapter) ctx.system.receptionist ! subscribe sensorWithAlarms(where, Set.empty) } Sensor, subscribing to alarms
  • 85. sealed trait SensorMessage case object Trigger extends SensorMessage case class AlarmsChanged( alarms: Set[ActorRef[Alarm.ActivitySeen]] ) extends SensorMessage def sensor(where: String): Behavior[SensorMessage] = Behaviors.setup { ctx => val adapter = ctx.messageAdapter[Listing] { case Alarm.serviceKey.Listing(alarms) => AlarmsChanged(alarms) } val subscribe = Subscribe(Alarm.serviceKey, adapter) ctx.system.receptionist ! subscribe sensorWithAlarms(where, Set.empty) } Sensor, subscribing to alarms
  • 86. sealed trait SensorMessage case object Trigger extends SensorMessage case class AlarmsChanged( alarms: Set[ActorRef[Alarm.ActivitySeen]] ) extends SensorMessage def sensor(where: String): Behavior[SensorMessage] = Behaviors.setup { ctx => val adapter = ctx.messageAdapter[Listing] { case Alarm.serviceKey.Listing(alarms) => AlarmsChanged(alarms) } val subscribe = Subscribe(Alarm.serviceKey, adapter) ctx.system.receptionist ! subscribe sensorWithAlarms(where, Set.empty) } Sensor, subscribing to alarms
  • 87. sealed trait SensorMessage case object Trigger extends SensorMessage case class AlarmsChanged( alarms: Set[ActorRef[Alarm.ActivitySeen]] ) extends SensorMessage def sensor(where: String): Behavior[SensorMessage] = Behaviors.setup { ctx => val adapter = ctx.messageAdapter[Listing] { case Alarm.serviceKey.Listing(alarms) => AlarmsChanged(alarms) } val subscribe = Subscribe(Alarm.serviceKey, adapter) ctx.system.receptionist ! subscribe sensorWithAlarms(where, Set.empty) } Sensor, subscribing to alarms
  • 88. sealed trait SensorMessage case object Trigger extends SensorMessage case class AlarmsChanged( alarms: Set[ActorRef[Alarm.ActivitySeen]] ) extends SensorMessage def sensor(where: String): Behavior[SensorMessage] = Behaviors.setup { ctx => val adapter = ctx.messageAdapter[Listing] { case Alarm.serviceKey.Listing(alarms) => AlarmsChanged(alarms) } val subscribe = Subscribe(Alarm.serviceKey, adapter) ctx.system.receptionist ! subscribe sensorWithAlarms(where, Set.empty) } Sensor, subscribing to alarms
  • 89. def sensorWithAlarms( where: String, alarms: Set[ActorRef[Alarm.ActivitySeen]] ): Behavior[SensorMessage] = Behaviors.receive { (ctx, msg) => msg match { case Trigger => val event = Alarm.ActivitySeen(where) alarms.foreach(_ ! event) Behaviors.same case Sensor.AlarmsChanged(newSetOfAlarms) => ctx.log.info(s"New set of alarms: {}", newSetOfAlarms) sensorWithAlarms(where, newSetOfAlarms) } } Sensor, react to alarm changes
  • 90. def sensorWithAlarms( where: String, alarms: Set[ActorRef[Alarm.ActivitySeen]] ): Behavior[SensorMessage] = Behaviors.receive { (ctx, msg) => msg match { case Trigger => val event = Alarm.ActivitySeen(where) alarms.foreach(_ ! event) Behaviors.same case Sensor.AlarmsChanged(newSetOfAlarms) => ctx.log.info(s"New set of alarms: {}", newSetOfAlarms) sensorWithAlarms(where, newSetOfAlarms) } } Sensor, react to alarm changes
  • 91. def sensorWithAlarms( where: String, alarms: Set[ActorRef[Alarm.ActivitySeen]] ): Behavior[SensorMessage] = Behaviors.receive { (ctx, msg) => msg match { case Trigger => val event = Alarm.ActivitySeen(where) alarms.foreach(_ ! event) Behaviors.same case Sensor.AlarmsChanged(newSetOfAlarms) => ctx.log.info(s"New set of alarms: {}", newSetOfAlarms) sensorWithAlarms(where, newSetOfAlarms) } } Sensor, react to alarm changes
  • 92. def sensorWithAlarms( where: String, alarms: Set[ActorRef[Alarm.ActivitySeen]] ): Behavior[SensorMessage] = Behaviors.receive { (ctx, msg) => msg match { case Trigger => val event = Alarm.ActivitySeen(where) alarms.foreach(_ ! event) Behaviors.same case Sensor.AlarmsChanged(newSetOfAlarms) => ctx.log.info(s"New set of alarms: {}", newSetOfAlarms) sensorWithAlarms(where, newSetOfAlarms) } } Sensor, react to alarm changes
  • 93. Cluster config val config = ConfigFactory.parseString( """ akka.actor.provider=cluster akka.remote.artery.enabled=true akka.remote.artery.transport=tcp # get a port from the OS akka.remote.artery.canonical.port=0 akka.remote.artery.canonical.host=127.0.0.1 # these are ok just because this is a sample akka.cluster.jmx.multi-mbeans-in-same-jvm=on akka.actor.warn-about-java-serializer-usage=off """)
  • 94. Programmatic cluster startup val system1 = ActorSystem( distributedAlarm(pinCode = "0000"), "alarm", config) val system2 = ActorSystem(sensor("window"), "alarm", config) val system3 = ActorSystem(sensor("door"), "alarm", config) // Note: in a real system you would not likely // run multiple nodes in the same JVM val node1 = Cluster(system1) val node2 = Cluster(system2) val node3 = Cluster(system3) // node 1 joins itself to form cluster node1.manager ! Join(node1.selfMember.address) // the other two joins that cluster node2.manager ! Join(node1.selfMember.address) node3.manager ! Join(node1.selfMember.address)
  • 95. Programmatic cluster startup val system1 = ActorSystem( distributedAlarm(pinCode = "0000"), "alarm", config) val system2 = ActorSystem(sensor("window"), "alarm", config) val system3 = ActorSystem(sensor("door"), "alarm", config) // Note: in a real system you would not likely // run multiple nodes in the same JVM val node1 = Cluster(system1) val node2 = Cluster(system2) val node3 = Cluster(system3) // node 1 joins itself to form cluster node1.manager ! Join(node1.selfMember.address) // the other two joins that cluster node2.manager ! Join(node1.selfMember.address) node3.manager ! Join(node1.selfMember.address)
  • 96. Programmatic cluster startup val system1 = ActorSystem( distributedAlarm(pinCode = "0000"), "alarm", config) val system2 = ActorSystem(sensor("window"), "alarm", config) val system3 = ActorSystem(sensor("door"), "alarm", config) // Note: in a real system you would not likely // run multiple nodes in the same JVM val node1 = Cluster(system1) val node2 = Cluster(system2) val node3 = Cluster(system3) // node 1 joins itself to form cluster node1.manager ! Join(node1.selfMember.address) // the other two joins that cluster node2.manager ! Join(node1.selfMember.address) node3.manager ! Join(node1.selfMember.address)
  • 97. Simulate some activity // at some point in time system2 ! Sensor.Trigger system3 ! Sensor.Trigger … [INFO] [17:48:27.456] New set of alarms: Set(Actor[akka:// alarm-system@127.0.0.1:54960/user#0]) [INFO] [17:48:27.511] New set of alarms: Set(Actor[akka:// alarm-system@127.0.0.1:54960/user#0]) [WARN] [17:48:29.021] EOEOEOE, activity detected: window [WARN] [17:48:31.011] EOEOEOE, activity detected: door
  • 98. Summary • On message - message another actor, change state or behavior • Types gives better guardrails and makes understanding the system easier • We can use the same abstraction for local and distributed
  • 99. How ready is it? • APIs not frozen (normally we keep binary compatibility in minor releases) - we expect only minor changes though • Pretty much the same since mid spring 2018 • Most likely to change - Typed Persistence • All cluster APIs and Cluster tools covered • Working towards a GA, hopefully this fall
  • 100. GitHub repo with all samples in this talk https://git.io/fAiZt Akka typed docs doc.akka.io/docs/akka/current/typed More resources blog.akka.io - news and articles discuss.akka.io - forums developer.lightbend.com - samples Further reading
  • 101. Questions? GitHub repo with all samples in this talk https://git.io/fAiZt