Distributed Systems vs.
CompositionalityDr. Roland Kuhn
@rolandkuhn — CTO of Actyx
Caveat:
This presentation shows unreleased APIs!
Weird starting point:
π calculus
What is a calculus?
• syntax for writing down a computation
• reduction rules for evaluating the syntax
4
π calculus: the syntax
5
Robin Milner et al, 1992
⇡ ::=
8><
>:
x(y) receive y along x
xhyi send y along x
⌧ unobservable action
(1)
P ::=
X
i2I
⇡i.Pi
��� P1|P2
��� new aP
��� !P��� 0 (2)
π calculus: the reductions
6
TAU : ⌧.P +M ! P (3)
REACT :
�x(y).P +M
����xhzi.Q+N
�!
�z/y P
��Q (4)
PAR :
P ! P
0
P |Q ! P
0|Q (5)
RES :
P ! P
0
newxP ! newxP
0 (6)
STRUCT :
P ! P
0
Q ! Q
0 if P ⌘ Q ^ P
0 ⌘ Q
0(7)
2
Robin Milner et al, 1992
An example reduction
7
P = new z
⇣(xhyi.0 + z(w).whyi.0)
��� x(u).uhvi.0��� xhzi.0
⌘possibility1
possibility2
An example reduction
8
P = new z
⇣0
��� yhvi.0��� xhzi.0
⌘
An example reduction
9
P = new z
⇣(xhyi.0 + z(w).whyi.0)
��� x(u).uhvi.0��� xhzi.0
⌘
possibility2
An example reduction
10
P = new z
⇣(xhyi.0 + z(w).whyi.0)
��� zhvi.0��� 0
⌘onlyonepossibility
An example reduction
11
P = new z
⇣vhyi.0
��� 0��� 0
⌘
An example reduction
12
P = vhyi.0
There’s more!
• structural congruence allows symbolic manipulation • rename, reorder sums, expand recursion, …
• bi-simulation describes functional equivalence
13
So, what is a calculus?
• a way to write down computations
• a means to reason about computations
• a tool to compose computations
14
Composition
Composition in the π calculus
• you can • run computations sequentially
• run computations concurrently
• synchronize concurrent computations
16
Composing processes
17
new cA
⇣Pclient
��� PserviceA
⌘
channelwhereserviceAisreachable
willsendtocAandeventuallyreactto
response
willreacttocAandeventuallysendbackaresponse
We need protocols!
What is a protocol?
• defines a communication discipline: • who can send what kind of message, and when
• which kinds of message to expect, and when
• each distributed process must adhere to the common protocol
• a global protocol can be checked for safety
19
Session types
• Session: a unit of conversation
• Session Type: the structure of a conversation,a sequence of interactions in acommunication-centric program model
• originally only binary sessions,multiparty session types introduced 2008
• primitives aresending, receiving, sequence, choice, recursion
20
http://groups.inf.ed.ac.uk/abcd/
Session types example
21
Sreqresp = !Request(params) . ?Response(result) (8)
Sreqresp = ?Request(params) . !Response(result) (9)
But is it safe? Does it compose?
22
Pclient PserviceA PbackendA
PserviceB PbackendB
Protocols don’t compose!
• at least not in general, as far as we know
• some cases are (mostly?) okay • non-cyclic
• non-interacting
• what a bummer!⟹ let’s find a smaller problem to solve
23
Composing Actor Behavior
Behavior composition
25
new cinternal
⇣PserviceA
��� PclientB
⌘
26
case class DoStuff(stuff: Stuff) case class DoIt(it: It) case class DoneSuccessfully(result: Result)
class MyActor(receptionist: ActorRef) extends Actor {
override def preStart(): Unit = receptionist ! Register def receive = initializing
def initializing: Receive = { case Registered => // do stuff context.become(running) }
def running: Receive = { case DoStuff(stuff) => context.actorOf(Props[Child]) ! DoIt(???) context.become(waitingForResult(stuff)) }
def waitingForResult(stuff: Stuff): Receive = { case DoneSuccessfully(result) => // do stuff, e.g. replying context.become(running) } }
We need reusable composable behavior snippets!
Radical idea: π calculus within!
• idea sparked while listening to Alex Prokopec
• create DSL inspired by π calculus • lifted representation of asynchronous actions
• combinators for sequential & parallel composition
28
What does it look like?
29
π calculus Akka Typed Sessions
new c P val serverChannel = channel[Command](128)
P initialize: Process[ActorRef[Request]]
π.P for { backend ← initialize server ← register(backend)} yield run(server, backend)
P|Q fork(task): Process[Unit]read(serverChannel) race timeout(1.second)getThingA join getThingB
x(y) read(serverChannel): Process[Command]
x❬y❭ serverChannel.ref ! msg(synchronous send operation not there, yet)
Example of a Server Process
30
def run(server: Channel[ServerCommand], backend: ActorRef[BackendCommand]) : Process[Nothing] = for { cmd ← read(server) } yield cmd match { case GetIt(which, replyTo) => val spinOff = talkWithBackend(which, backend) .foreach(thing => replyTo ! GotIt(thing.weird)) fork(spinOff race timeout(5.seconds)) .then(run(server, backend)) }
Example of a Server Process
31
def talkWithBackend(which: String, backend: ActorRef[BackendCommand]) : Process[TheThing] = { val code = channel[Code](1) val thing = channel[TheThing](1) backend ! GetThingCode(0xdeadbeefcafeL, code.ref) for { c ← readAndSeal(code) } yield { c.magicChest ! GetTheThing(which, thing.ref) readAndSeal(thing) }}
What does this have to do with Akka?
• Akka Typed Behavior to interpret Process
• channel reference is a lean child ActorRef
• this closes the gap between the Actor Model and CSP/π • Actors have stable identity but only one channel
• anonymous Processes have multiple channels(with identity)
32
Outlook
Tracking effects
• lifted representation of Process allows tracking of effects
• embedding of session type in π calculus exists
• verify Process against a session type
34
Irresponsible Speculation
35
// Effects is similar to HList (but a tree) trait Process[T, E <: Effects] { def map[U, UE <: Effects](f: T => Process[U, UE]) :Process[U, UE :*: E] def join[U, UE <: Effects](p: Process[U, UE]) :Process[(T, U), UE :+: E] def race // ??? }
def read[T](c: Channel[T]): Process[T, Recv[c.type]] def write[T](ref: ActorRef[T]): Process[T, Send[ref.type]]
def fork[T, TE <: Effects](p: Process[T, TE]) : Process[Unit, NoEffect :|: TE]
Current State
• behaviors can be composed both sequentially and concurrently
• effects are not yet tracked
• Scribble generator for Scala not yet there
• theoretical work at Imperial College, London(Prof. Nobuko Yoshida & Alceste Scalas)
36
©Actyx AG 2016 – All Rights Reserved
Top Related