SlideShare a Scribd company logo
Akka Typed:
Between Session Types
and the Actor Model
Dr. Roland Kuhn
@rolandkuhn — Akka Tech Lead
Actor Model
The Actor Model
• Hewitt, Bishop, Steiger,

“A Universal Modular ACTOR Formalism for Artificial
Intelligence”, IJCAI’73, pp 235–245
• a model of distributed independent agents
• in response to an incoming message an Actor can
• create a finite number of Actors
• send a finite number of messages to Actors it knows
• designate the behavior to be applied to the next message
3
Concrete Implementation: Akka
4
case class Greet(whom: String)
class Greeter extends Actor {
def receive = {
case Greet(whom) =>
sender() ! s"Hello $whom!"
val delegate = context.actorOf(grumpyProps)
context.become(grumpy(delegate))
}
def grumpy(delegate: ActorRef): Receive = {
case g: Greet => delegate forward g
}
}
val grumpyProps = Props(new Actor {
def receive = {
case Greet(whom) => sender() ! s"Go away, $whom!"
}
})
Motivation
Initial Motivation
• make Actors re-factoring friendly
• avoid stupid mistakes

(i.e. provide some weak safety properties)
6
Introducing Akka Typed
The Flaws of Previous Implementations
• retaining sender() is just not feasible
• this feature is inherently dynamic and therefore must go
• defining union types for multiple input types proved
too complex
• TypedChannels used a type map based on HList
• verbose syntax and cryptic error messages
• use only single type parameter and subsume other types
via dedicated adapters (child Actors)
8
The Current Implementation
• parameterized ActorRef accepts type T
• parameterized Behavior responds to type T
• actor creation turns Behavior[T] via Props[T]
into ActorRef[-T]
• implemented as a thin layer on top of untyped
actors
• separated the logic from its execution, no more
Actor trait
9
Behavior is King, no more Actor trait
10
object Server {
sealed trait Command
case class Get(id: Int)(val replyTo: ActorRef[Got]) extends Command
case class Put(name: String, ref: ActorRef[OtherCommand]) extends Command
case class Got(id: Int, contents: Map[String, ActorRef[OtherCommand]])
val initial: Behavior[Command] = withMap(Map.empty)
private def withMap(map: Map[String, ActorRef[OtherCommand]]) =
Total[Command] {
case g @ Get(id) =>
g.replyTo ! Got(id, Map.empty)
Same
case Put(name, ref) =>
withMap(map.updated(name, ref))
}
}
What can we do with it?
Encoding Types with Members
12
class MyClass {
def myMethod(id: Int): String
def otherMethod(name: String): Unit
protected def helper(arg: Double): Unit
}
Encoding Types with Members
• Typed Actors provide complete modules with members
• Typed Actors can encode more flexible access privileges
• more verbose due to syntax being optimized for classes
13
object MyClass {
sealed trait AllCommand
sealed trait Command extends AllCommand
case class MyMethod(id: Int)(replyTo: ActorRef[String]) extends Command
case class OtherMethod(name: String) extends Command
case class Helper(arg: Double) extends AllCommand
val behavior: Behavior[Command] = behavior(42).narrow
private def behavior(x: Int): Behavior[AllCommand] = ???
}
Calling Methods
14
object MyClassDemo {
import MyClass._
val myClass: MyClass = ???
val myActor: ActorRef[Command] = ???
implicit val t: Timeout = ???
myClass.otherMethod("John")
myActor!OtherMethod("John")
val result = myClass.myMethod(42)
val future = myActor?MyMethod(42)
}
But Actors can do more: Protocols
15
object Protocol {
case class GetSession(replyTo: ActorRef[GetSessionResult])
sealed trait GetSessionResult
case class ActiveSession(service: ActorRef[SessionCommand])
extends GetSessionResult with AuthenticateResult
case class NewSession(auth: ActorRef[Authenticate])
extends GetSessionResult
case class Authenticate(username: String,
password: String,
replyTo: ActorRef[AuthenticateResult])
sealed trait AuthenticateResult
case object FailedSession extends AuthenticateResult
trait SessionCommand
}
But Actors can do more: Protocols
16
Session Types
Attempt at a Definition
• Session: aunitofconversation
• Session Type: thestructureofaconversation,

a sequence of interactions in a communication-
centric program model
• originally only binary sessions, multiparty sessions
introduced 2008
• primitives are

sending,receiving,sequence,choice,recursion
18
Scribble
• commonly used language for defining protocols
• defines the global protocol for all participants
• local projection for a single participant preserves safety
• automatic generation of FSA for local runtime validation
• type discipline for local processes requires support
for linear types from the host language
• where that is unavailable use dynamic validation
19
Question
• Can safety be retained while allowing sessions with
dynamically added and removed participants?
20
Question
• Does distributed computing fundamentally need
nominal types to agree on semantics?
21
Case Study: Type-Safe Receptionist
22
object Receptionist {
trait AbstractServiceKey {
type Type
}
trait ServiceKey[T] extends AbstractServiceKey {
final override type Type = T
}
sealed trait Command
final case class Register[T](key: ServiceKey[T], address: ActorRef[T])
(val replyTo: ActorRef[Registered[T]]) extends Command
final case class Find[T](key: ServiceKey[T])(val replyTo: ActorRef[Listing[T]])
extends Command
final case class Registered[T](key: ServiceKey[T], address: ActorRef[T])
final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]])
...
}
23
object Receptionist {
...
val behavior: Behavior[Command] = behavior(TypedMultiMap.empty)
private type KV[K <: AbstractServiceKey] = ActorRef[K#Type]
private def behavior(map: TypedMultiMap[AbstractServiceKey, KV]) =
Full[Command] {
case Msg(ctx, r: Register[t]) =>
ctx.watch(r.address)
r.replyTo ! Registered(r.key, r.address)
behavior(map.inserted(r.key)(r.address))
case Msg(ctx, f: Find[t]) =>
val set = map get f.key
f.replyTo ! Listing(f.key, set)
Same
case Sig(ctx, Terminated(ref)) =>
behavior(map valueRemoved ref)
}
}
Question
• the interrupt feature of Scribble introduces non-
determinism since messages can be arbitrarily
delayed
• How much does the theory hinge on guaranteed
delivery?
• Does the session just cease to exist when nodes fail?
24
Linear Types
or
Dynamic Actors?
Question
• protocol progress between fixed participants
implies the destruction of knowledge
• Can this notion be replaced by requiring the
acquisition or deduction of new knowledge?
26
Question
• Instead of relying upon consensus, shouldn’t we
maximize the use of causality and causal
consistency?
27
Lloyd, Freedman, Kaminsky, Andersen: «Don’t Settle for Eventual:
Scalable Causal Consistency for Wide-Area Storage with COPS», SOSP’11, ACM 2011
Dynamic Validation
Dynamic Validation of Actor Behavior
• pure internal formulation using an abstract
machine (process algebra)
• interpreter can run local projection of protocol
• rejects sending untimely messages
• rejects receiving from inactive channels
• due to at-most-once delivery FSA can only advance
upon reception of external input (proof of progress)
29
Question
• Given the following requirements:
• sequencing of actions
• dynamic decision how to continue
• recursion
• composition of actions
• injection of plain values
• Is there another abstraction than Monad to
formulate the API?
30
©Typesafe 2015 – All Rights Reserved

More Related Content

PDF
Taming Distribution: Formal Protocols for Akka Typed
PDF
Project Gålbma – Actors vs Types
PDF
​"Delegates, Delegates everywhere" Владимир Миронов
PDF
"Kotlin и rx в android" Дмитрий Воронин (Avito)
PDF
360|iDev
PDF
Kotlin on Android: Delegate with pleasure
PDF
Madrid gug - sacando partido a las transformaciones ast de groovy
PPTX
Groovy Api Tutorial
Taming Distribution: Formal Protocols for Akka Typed
Project Gålbma – Actors vs Types
​"Delegates, Delegates everywhere" Владимир Миронов
"Kotlin и rx в android" Дмитрий Воронин (Avito)
360|iDev
Kotlin on Android: Delegate with pleasure
Madrid gug - sacando partido a las transformaciones ast de groovy
Groovy Api Tutorial

What's hot (19)

PDF
G3 Summit 2016 - Taking Advantage of Groovy Annotations
PDF
The Ring programming language version 1.5.1 book - Part 174 of 180
PDF
The Ring programming language version 1.9 book - Part 98 of 210
PPTX
Introduction to kotlin + spring boot demo
PPTX
Groovy grails types, operators, objects
ODP
Knolx session
PDF
Martin Fowler's Refactoring Techniques Quick Reference
PDF
core.logic introduction
PPS
CS101- Introduction to Computing- Lecture 29
PDF
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
PPTX
Python programming: Anonymous functions, String operations
PPTX
PPTX
Introduction to Gremlin
PDF
Pragmatic Real-World Scala (short version)
PDF
Kotlin Advanced - Apalon Kotlin Sprint Part 3
PDF
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
ODP
Meetup slides
PDF
The Ring programming language version 1.6 book - Part 40 of 189
PDF
Scalaz 8 vs Akka Actors
G3 Summit 2016 - Taking Advantage of Groovy Annotations
The Ring programming language version 1.5.1 book - Part 174 of 180
The Ring programming language version 1.9 book - Part 98 of 210
Introduction to kotlin + spring boot demo
Groovy grails types, operators, objects
Knolx session
Martin Fowler's Refactoring Techniques Quick Reference
core.logic introduction
CS101- Introduction to Computing- Lecture 29
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
Python programming: Anonymous functions, String operations
Introduction to Gremlin
Pragmatic Real-World Scala (short version)
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Meetup slides
The Ring programming language version 1.6 book - Part 40 of 189
Scalaz 8 vs Akka Actors
Ad

Viewers also liked (12)

PDF
Distributed systems vs compositionality
PDF
The Newest in Session Types
PDF
Reactive Design Patterns — J on the Beach
PDF
Reactive Streams: Handling Data-Flow the Reactive Way
PDF
Go Reactive: Blueprint for Future Applications
PDF
An Actor Model in Go
PDF
HBase RowKey design for Akka Persistence
PDF
Akka cluster overview at 010dev
PDF
Akka and AngularJS – Reactive Applications in Practice
PDF
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
PDF
Akka Streams and HTTP
PPTX
The Actor Model - Towards Better Concurrency
Distributed systems vs compositionality
The Newest in Session Types
Reactive Design Patterns — J on the Beach
Reactive Streams: Handling Data-Flow the Reactive Way
Go Reactive: Blueprint for Future Applications
An Actor Model in Go
HBase RowKey design for Akka Persistence
Akka cluster overview at 010dev
Akka and AngularJS – Reactive Applications in Practice
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
Akka Streams and HTTP
The Actor Model - Towards Better Concurrency
Ad

Similar to Akka Typed — between Session Types and the Actor Model (20)

PPTX
Scala Back to Basics: Type Classes
PPTX
Improving Correctness with Types
PDF
Demystifying Type Class derivation with Shapeless
PDF
Kotlin Delegates: Reduce the boilerplate
PDF
Scaling modern JVM applications with Akka toolkit
PDF
Expression trees in C#
PPTX
Improving Correctness With Type - Goto Con Berlin
PPTX
Improving Correctness with Types Kats Conf
PDF
aming distribution: formal protocols for Akka Typed
ODP
Functions In Scala
PPTX
Scala best practices
PDF
Oleksii Holub "Expression trees in C#"
PPTX
Scala 3 Is Coming: Martin Odersky Shares What To Know
PDF
Message-based communication patterns in distributed Akka applications
PDF
Activator and Reactive at Play NYC meetup
PDF
CAVE Overview
PDF
Akka with Scala
PDF
Futzing with actors (etc.)
PDF
Scala Back to Basics: Type Classes
Improving Correctness with Types
Demystifying Type Class derivation with Shapeless
Kotlin Delegates: Reduce the boilerplate
Scaling modern JVM applications with Akka toolkit
Expression trees in C#
Improving Correctness With Type - Goto Con Berlin
Improving Correctness with Types Kats Conf
aming distribution: formal protocols for Akka Typed
Functions In Scala
Scala best practices
Oleksii Holub "Expression trees in C#"
Scala 3 Is Coming: Martin Odersky Shares What To Know
Message-based communication patterns in distributed Akka applications
Activator and Reactive at Play NYC meetup
CAVE Overview
Akka with Scala
Futzing with actors (etc.)

Akka Typed — between Session Types and the Actor Model

  • 1. Akka Typed: Between Session Types and the Actor Model Dr. Roland Kuhn @rolandkuhn — Akka Tech Lead
  • 3. The Actor Model • Hewitt, Bishop, Steiger,
 “A Universal Modular ACTOR Formalism for Artificial Intelligence”, IJCAI’73, pp 235–245 • a model of distributed independent agents • in response to an incoming message an Actor can • create a finite number of Actors • send a finite number of messages to Actors it knows • designate the behavior to be applied to the next message 3
  • 4. Concrete Implementation: Akka 4 case class Greet(whom: String) class Greeter extends Actor { def receive = { case Greet(whom) => sender() ! s"Hello $whom!" val delegate = context.actorOf(grumpyProps) context.become(grumpy(delegate)) } def grumpy(delegate: ActorRef): Receive = { case g: Greet => delegate forward g } } val grumpyProps = Props(new Actor { def receive = { case Greet(whom) => sender() ! s"Go away, $whom!" } })
  • 6. Initial Motivation • make Actors re-factoring friendly • avoid stupid mistakes
 (i.e. provide some weak safety properties) 6
  • 8. The Flaws of Previous Implementations • retaining sender() is just not feasible • this feature is inherently dynamic and therefore must go • defining union types for multiple input types proved too complex • TypedChannels used a type map based on HList • verbose syntax and cryptic error messages • use only single type parameter and subsume other types via dedicated adapters (child Actors) 8
  • 9. The Current Implementation • parameterized ActorRef accepts type T • parameterized Behavior responds to type T • actor creation turns Behavior[T] via Props[T] into ActorRef[-T] • implemented as a thin layer on top of untyped actors • separated the logic from its execution, no more Actor trait 9
  • 10. Behavior is King, no more Actor trait 10 object Server { sealed trait Command case class Get(id: Int)(val replyTo: ActorRef[Got]) extends Command case class Put(name: String, ref: ActorRef[OtherCommand]) extends Command case class Got(id: Int, contents: Map[String, ActorRef[OtherCommand]]) val initial: Behavior[Command] = withMap(Map.empty) private def withMap(map: Map[String, ActorRef[OtherCommand]]) = Total[Command] { case g @ Get(id) => g.replyTo ! Got(id, Map.empty) Same case Put(name, ref) => withMap(map.updated(name, ref)) } }
  • 11. What can we do with it?
  • 12. Encoding Types with Members 12 class MyClass { def myMethod(id: Int): String def otherMethod(name: String): Unit protected def helper(arg: Double): Unit }
  • 13. Encoding Types with Members • Typed Actors provide complete modules with members • Typed Actors can encode more flexible access privileges • more verbose due to syntax being optimized for classes 13 object MyClass { sealed trait AllCommand sealed trait Command extends AllCommand case class MyMethod(id: Int)(replyTo: ActorRef[String]) extends Command case class OtherMethod(name: String) extends Command case class Helper(arg: Double) extends AllCommand val behavior: Behavior[Command] = behavior(42).narrow private def behavior(x: Int): Behavior[AllCommand] = ??? }
  • 14. Calling Methods 14 object MyClassDemo { import MyClass._ val myClass: MyClass = ??? val myActor: ActorRef[Command] = ??? implicit val t: Timeout = ??? myClass.otherMethod("John") myActor!OtherMethod("John") val result = myClass.myMethod(42) val future = myActor?MyMethod(42) }
  • 15. But Actors can do more: Protocols 15 object Protocol { case class GetSession(replyTo: ActorRef[GetSessionResult]) sealed trait GetSessionResult case class ActiveSession(service: ActorRef[SessionCommand]) extends GetSessionResult with AuthenticateResult case class NewSession(auth: ActorRef[Authenticate]) extends GetSessionResult case class Authenticate(username: String, password: String, replyTo: ActorRef[AuthenticateResult]) sealed trait AuthenticateResult case object FailedSession extends AuthenticateResult trait SessionCommand }
  • 16. But Actors can do more: Protocols 16
  • 18. Attempt at a Definition • Session: aunitofconversation • Session Type: thestructureofaconversation,
 a sequence of interactions in a communication- centric program model • originally only binary sessions, multiparty sessions introduced 2008 • primitives are
 sending,receiving,sequence,choice,recursion 18
  • 19. Scribble • commonly used language for defining protocols • defines the global protocol for all participants • local projection for a single participant preserves safety • automatic generation of FSA for local runtime validation • type discipline for local processes requires support for linear types from the host language • where that is unavailable use dynamic validation 19
  • 20. Question • Can safety be retained while allowing sessions with dynamically added and removed participants? 20
  • 21. Question • Does distributed computing fundamentally need nominal types to agree on semantics? 21
  • 22. Case Study: Type-Safe Receptionist 22 object Receptionist { trait AbstractServiceKey { type Type } trait ServiceKey[T] extends AbstractServiceKey { final override type Type = T } sealed trait Command final case class Register[T](key: ServiceKey[T], address: ActorRef[T]) (val replyTo: ActorRef[Registered[T]]) extends Command final case class Find[T](key: ServiceKey[T])(val replyTo: ActorRef[Listing[T]]) extends Command final case class Registered[T](key: ServiceKey[T], address: ActorRef[T]) final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]]) ... }
  • 23. 23 object Receptionist { ... val behavior: Behavior[Command] = behavior(TypedMultiMap.empty) private type KV[K <: AbstractServiceKey] = ActorRef[K#Type] private def behavior(map: TypedMultiMap[AbstractServiceKey, KV]) = Full[Command] { case Msg(ctx, r: Register[t]) => ctx.watch(r.address) r.replyTo ! Registered(r.key, r.address) behavior(map.inserted(r.key)(r.address)) case Msg(ctx, f: Find[t]) => val set = map get f.key f.replyTo ! Listing(f.key, set) Same case Sig(ctx, Terminated(ref)) => behavior(map valueRemoved ref) } }
  • 24. Question • the interrupt feature of Scribble introduces non- determinism since messages can be arbitrarily delayed • How much does the theory hinge on guaranteed delivery? • Does the session just cease to exist when nodes fail? 24
  • 26. Question • protocol progress between fixed participants implies the destruction of knowledge • Can this notion be replaced by requiring the acquisition or deduction of new knowledge? 26
  • 27. Question • Instead of relying upon consensus, shouldn’t we maximize the use of causality and causal consistency? 27 Lloyd, Freedman, Kaminsky, Andersen: «Don’t Settle for Eventual: Scalable Causal Consistency for Wide-Area Storage with COPS», SOSP’11, ACM 2011
  • 29. Dynamic Validation of Actor Behavior • pure internal formulation using an abstract machine (process algebra) • interpreter can run local projection of protocol • rejects sending untimely messages • rejects receiving from inactive channels • due to at-most-once delivery FSA can only advance upon reception of external input (proof of progress) 29
  • 30. Question • Given the following requirements: • sequencing of actions • dynamic decision how to continue • recursion • composition of actions • injection of plain values • Is there another abstraction than Monad to formulate the API? 30
  • 31. ©Typesafe 2015 – All Rights Reserved