SlideShare a Scribd company logo
Taming Distribution:
Formal Protocols
for Akka Typed
Dr. Roland Kuhn
@rolandkuhn — CTO of Actyx
Distribution
=
Concurrency + Partial Failure
Distribution
=
Concurrency + Partial Failure
Distribution
=
Concurrency + Partial Failure
Actors model distribution.
Concurrency implies Nondeterminism.
Distribution implies more Nondeterminism.
Concurrency implies Nondeterminism.
Distribution implies more Nondeterminism.
Causality restricts Nondeterminism.
Some causality comes naturally.
Akka Typed Receptionist API
trait ServiceKey[T]
sealed trait Command
final case class Register[T](key: ServiceKey[T], address: ActorRef[T],
replyTo: ActorRef[Registered[T]]) extends Command
final case class Registered[T](key: ServiceKey[T], address: ActorRef[T])
final case class Find[T](key: ServiceKey[T], replyTo: ActorRef[Listing[T]]) extends Command
final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]])
… with Unregister support
trait ServiceKey[T]
sealed trait Command
final case class Register[T](key: ServiceKey[T], address: ActorRef[T],
replyTo: ActorRef[Registered[T]]) extends Command
final case class Registered[T](key: ServiceKey[T], address: ActorRef[T], handle: ActorRef[Unregister])
final case class Unregister(replyTo: ActorRef[Unregistered])
final case class Unregistered()
final case class Find[T](key: ServiceKey[T], replyTo: ActorRef[Listing[T]]) extends Command
final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]])
For everything that is not fixed by causality
coordination is needed.
Static knowledge avoids coordination.
Cluster Receptionist
Cluster Receptionist
• use FQCN of service keys as known identifier
Cluster Receptionist
• use FQCN of service keys as known identifier
• local resolution establishes static type-safety
Cluster Receptionist
• use FQCN of service keys as known identifier
• local resolution establishes static type-safety
• CRDT map from keys to sets of ActorRefs
Natural causality is not enough!
Example: payment with audit
Messages for a payment system
case object AuditService extends ServiceKey[LogActivity]
case class LogActivity(who: ActorRef[Nothing], what: String,
id: Long, replyTo: ActorRef[ActivityLogged])
case class ActivityLogged(who: ActorRef[Nothing], id: Long)
Messages for a payment system
case object AuditService extends ServiceKey[LogActivity]
case class LogActivity(who: ActorRef[Nothing], what: String,
id: Long, replyTo: ActorRef[ActivityLogged])
case class ActivityLogged(who: ActorRef[Nothing], id: Long)
sealed trait PaymentService
case class Authorize(payer: URI, amount: BigDecimal, id: UUID, replyTo: ActorRef[PaymentResult])
extends PaymentService
case class Capture(id: UUID, amount: BigDecimal, replyTo: ActorRef[PaymentResult])
extends PaymentService
case class Void(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService
case class Refund(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService
Messages for a payment system
case object AuditService extends ServiceKey[LogActivity]
case class LogActivity(who: ActorRef[Nothing], what: String,
id: Long, replyTo: ActorRef[ActivityLogged])
case class ActivityLogged(who: ActorRef[Nothing], id: Long)
sealed trait PaymentService
case class Authorize(payer: URI, amount: BigDecimal, id: UUID, replyTo: ActorRef[PaymentResult])
extends PaymentService
case class Capture(id: UUID, amount: BigDecimal, replyTo: ActorRef[PaymentResult])
extends PaymentService
case class Void(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService
case class Refund(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService
sealed trait PaymentResult
case class PaymentSuccess(id: UUID) extends PaymentResult
case class PaymentRejected(id: UUID, reason: String) extends PaymentResult
case class IdUnkwown(id: UUID) extends PaymentResult
Akka Typed crash course
case class Greet(whom: String)
class Greeter extends akka.actor.Actor {
def receive = {
case Greet(whom) => println(s"Hello $whom!")
}
}
Akka Typed crash course
case class Greet(whom: String)
class Greeter extends akka.actor.Actor {
def receive = {
case Greet(whom) => println(s"Hello $whom!")
}
}
object Greeter {
import akka.typed.scaladsl.Actor
val behavior =
Actor.immutable[Greet] { (ctx, greet) =>
println(s"Hello ${greet.whom}!")
Actor.same
}
}
First actor: do the audit
sealed trait Msg
private case object AuditDone extends Msg
private case object PaymentDone extends Msg
private def doAudit(audit: ActorRef[LogActivity], who: ActorRef[AuditDone.type], msg: String) =
Actor.deferred[ActivityLogged] { ctx =>
val id = Random.nextLong()
audit ! LogActivity(who, msg, id, ctx.self)
ctx.schedule(3.seconds, ctx.self, ActivityLogged(null, 0L))
Actor.immutable { (ctx, msg) =>
if (msg.who == null) throw new TimeoutException
else if (msg.id != id) throw new IllegalStateException
else {
who ! AuditDone
Actor.stopped
}
}
}
Second actor: do the payment
private def doPayment(from: URI, amount: BigDecimal, payments: ActorRef[PaymentService],
replyTo: ActorRef[PaymentDone.type]) =
Actor.deferred[PaymentResult] { ctx =>
val uuid = UUID.randomUUID()
payments ! Authorize(from, amount, uuid, ctx.self)
ctx.schedule(3.seconds, ctx.self, IdUnkwown(null))
Actor.immutable {
case (ctx, PaymentSuccess(`uuid`)) =>
payments ! Capture(uuid, amount, ctx.self)
Actor.immutable {
case (ctx, PaymentSuccess(`uuid`)) =>
replyTo ! PaymentDone
Actor.stopped
}
// otherwise die with MatchError
}
}
Third actor: orchestration of the process
def getMoney[R](from: URI, amount: BigDecimal,
payments: ActorRef[PaymentService], audit: ActorRef[LogActivity],
replyTo: ActorRef[R], msg: R) =
Actor.deferred[Msg] { ctx =>
ctx.watch(ctx.spawn(doAudit(audit, ctx.self, "starting payment"), "preAudit"))
Actor.immutable[Msg] {
case (ctx, AuditDone) =>
ctx.watch(ctx.spawn(doPayment(from, amount, payments, ctx.self), "payment"))
Actor.immutable[Msg] {
case (ctx, PaymentDone) =>
ctx.watch(ctx.spawn(doAudit(audit, ctx.self, "payment finished"), "postAudit"))
Actor.immutable[Msg] {
case (ctx, AuditDone) =>
replyTo ! msg
Actor.stopped
}
} onSignal terminateUponChildFailure
} onSignal terminateUponChildFailure
}
code can employ knowledge in wrong order
or
existing knowledge is not used at all
What if we prescribe effects and their order?
Which steps shall be done?
• send audit log, get confirmation for that
• send Authorize request, get confirmation
• send Capture request, get confirmation
• send audit log, get confirmation
Akka Typed Session: protocol definition
object GetMoneyProtocol extends Protocol {
type Session = //
Send[LogActivity] :: // preAudit
Read[ActivityLogged] :: //
Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate
Send[Authorize] :: // do payment
Read[PaymentResult] :: //
Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate
Send[Capture] :: //
Read[PaymentResult] :: //
Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate
Send[LogActivity] :: // postAudit
Read[ActivityLogged] :: //
Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate
_0
}
First process: do the audit
private def doAudit(audit: ActorRef[LogActivity], who: ActorRef[Nothing], msg: String) =
OpDSL[ActivityLogged] { implicit opDSL =>
val id = Random.nextLong()
for {
self <- opProcessSelf
_ <- opSend(audit, LogActivity(who, msg, id, self))
ActivityLogged(`who`, `id`) <- opRead
} yield Done
}.withTimeout(3.seconds)
/*
* the return type is
* Process[ActivityLogged, Done,
* Send[LogActivity] :: Read[ActivityLogged] ::
* Choice[(Halt :: _0) :+: _0 :+: CNil] :: _0]
*/
Second process: do the payment
private def doPayment(from: URI, amount: BigDecimal, payments: ActorRef[PaymentService]) =
OpDSL[PaymentResult] { implicit opDSL =>
val uuid = UUID.randomUUID()
for {
self <- opProcessSelf
_ <- opSend(payments, Authorize(from, amount, uuid, self))
PaymentSuccess(`uuid`) <- opRead
_ <- opSend(payments, Capture(uuid, amount, self))
PaymentSuccess(`uuid`) <- opRead
} yield Done
}.withTimeout(3.seconds)
/*
* the return type is
* Process[PaymentResult, Done,
* Send[Authorize] :: Read[PaymentResult] ::
* Choice[(Halt :: _0) :+: _0 :+: CNil] ::
* Send[Capture] :: Read[PaymentResult] ::
* Choice[(Halt :: _0) :+: _0 :+: CNil] :: _0]
*/
Third process: orchestrate and verify
// this useful process is provided by the Session DSL and talks to the Receptionist
def getService[T](key: ServiceKey[T]): Operation[Listing[T], ActorRef[T], _0]
def getMoney[R](from: URI, amount: BigDecimal,
payments: ActorRef[PaymentService],
replyTo: ActorRef[R], msg: R) =
OpDSL[Nothing] { implicit opDSL =>
for {
self <- opProcessSelf
audit <- opCall(getService(AuditService) .named("getAuditService"))
_ <- opCall(doAudit(audit, self, "starting payment").named("preAudit"))
_ <- opCall(doPayment(from, amount, payments) .named("payment"))
_ <- opCall(doAudit(audit, self, "payment finished").named("postAudit"))
} yield replyTo ! msg
}
Third process: orchestrate and verify
// this useful process is provided by the Session DSL and talks to the Receptionist
def getService[T](key: ServiceKey[T]): Operation[Listing[T], ActorRef[T], _0]
def getMoney[R](from: URI, amount: BigDecimal,
payments: ActorRef[PaymentService],
replyTo: ActorRef[R], msg: R) =
OpDSL[Nothing] { implicit opDSL =>
for {
self <- opProcessSelf
audit <- opCall(getService(AuditService) .named("getAuditService"))
_ <- opCall(doAudit(audit, self, "starting payment").named("preAudit"))
_ <- opCall(doPayment(from, amount, payments) .named("payment"))
_ <- opCall(doAudit(audit, self, "payment finished").named("postAudit"))
} yield replyTo ! msg
}
// compile-time verification (TODO: should be a macro)
private def verify = E.vetExternalProtocol(GetMoneyProtocol, getMoney(???, ???, ???, ???, ???))
Conclusion:
There is a lot on the table,
get involved!
https://github.com/rkuhn/akka-typed-session

More Related Content

What's hot

Groovy Api Tutorial
Groovy Api  TutorialGroovy Api  Tutorial
Groovy Api Tutorial
guligala
 
つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~
kamedon39
 
つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版
kamedon39
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
Muhammad Abdullah
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
Husain Dalal
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
Norman Richards
 
The Ring programming language version 1.6 book - Part 40 of 189
The Ring programming language version 1.6 book - Part 40 of 189The Ring programming language version 1.6 book - Part 40 of 189
The Ring programming language version 1.6 book - Part 40 of 189
Mahmoud Samir Fayed
 
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
CloudxLab
 
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Greach 2015   AST – Groovy Transformers: More than meets the eye!Greach 2015   AST – Groovy Transformers: More than meets the eye!
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Iván López Martín
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
tdc-globalcode
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
Scala
ScalaScala
The Logical Burrito - pattern matching, term rewriting and unification
The Logical Burrito - pattern matching, term rewriting and unificationThe Logical Burrito - pattern matching, term rewriting and unification
The Logical Burrito - pattern matching, term rewriting and unification
Norman Richards
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
Chandra Sekhar Nayak
 
Introduction to Gremlin
Introduction to GremlinIntroduction to Gremlin
Introduction to Gremlin
Max De Marzi
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 

What's hot (16)

Groovy Api Tutorial
Groovy Api  TutorialGroovy Api  Tutorial
Groovy Api Tutorial
 
つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~
 
つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
 
The Ring programming language version 1.6 book - Part 40 of 189
The Ring programming language version 1.6 book - Part 40 of 189The Ring programming language version 1.6 book - Part 40 of 189
The Ring programming language version 1.6 book - Part 40 of 189
 
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
 
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Greach 2015   AST – Groovy Transformers: More than meets the eye!Greach 2015   AST – Groovy Transformers: More than meets the eye!
Greach 2015 AST – Groovy Transformers: More than meets the eye!
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Scala
ScalaScala
Scala
 
The Logical Burrito - pattern matching, term rewriting and unification
The Logical Burrito - pattern matching, term rewriting and unificationThe Logical Burrito - pattern matching, term rewriting and unification
The Logical Burrito - pattern matching, term rewriting and unification
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
 
Introduction to Gremlin
Introduction to GremlinIntroduction to Gremlin
Introduction to Gremlin
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 

Similar to Taming Distribution: Formal Protocols for Akka Typed

i need to write a return type function that takes information about th.docx
i need to write a return type function that takes information about th.docxi need to write a return type function that takes information about th.docx
i need to write a return type function that takes information about th.docx
hendriciraida
 
i need to modify this c++ so when the user enter services thats not an.docx
i need to modify this c++ so when the user enter services thats not an.docxi need to modify this c++ so when the user enter services thats not an.docx
i need to modify this c++ so when the user enter services thats not an.docx
hendriciraida
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
Matthias Noback
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Dan Robinson
 
Creating an Uber Clone - Part XXXII.pdf
Creating an Uber Clone - Part XXXII.pdfCreating an Uber Clone - Part XXXII.pdf
Creating an Uber Clone - Part XXXII.pdf
ShaiAlmog1
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
danwrong
 
Introducing the WSO2 Complex Event Processor
Introducing the WSO2 Complex Event ProcessorIntroducing the WSO2 Complex Event Processor
Introducing the WSO2 Complex Event Processor
WSO2
 
Serverless stateful
Serverless statefulServerless stateful
Serverless stateful
Patrick Di Loreto
 
CAVE Overview
CAVE OverviewCAVE Overview
CAVE Overview
vdumitrescu
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con Berlin
Iain Hull
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
Christoffer Noring
 
Rajeev oops 2nd march
Rajeev oops 2nd marchRajeev oops 2nd march
Rajeev oops 2nd march
Rajeev Sharan
 
i want to add to this c++ code a condition so that you can only chose.docx
i want to add to this c++ code a condition so that you can only chose.docxi want to add to this c++ code a condition so that you can only chose.docx
i want to add to this c++ code a condition so that you can only chose.docx
hendriciraida
 
ZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół ScalacZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół Scalac
Scalac
 
Serverless Stateful Architecture
Serverless Stateful ArchitectureServerless Stateful Architecture
Serverless Stateful Architecture
Patrick Di Loreto
 
Coordinating non blocking io melb-clj
Coordinating non blocking io melb-cljCoordinating non blocking io melb-clj
Coordinating non blocking io melb-clj
Logan Campbell
 
Small pieces loosely joined
Small pieces loosely joinedSmall pieces loosely joined
Small pieces loosely joined
ennui2342
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developers
jessitron
 
Creating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdfCreating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdf
ShaiAlmog1
 
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
Publicis Sapient Engineering
 

Similar to Taming Distribution: Formal Protocols for Akka Typed (20)

i need to write a return type function that takes information about th.docx
i need to write a return type function that takes information about th.docxi need to write a return type function that takes information about th.docx
i need to write a return type function that takes information about th.docx
 
i need to modify this c++ so when the user enter services thats not an.docx
i need to modify this c++ so when the user enter services thats not an.docxi need to modify this c++ so when the user enter services thats not an.docx
i need to modify this c++ so when the user enter services thats not an.docx
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
 
Creating an Uber Clone - Part XXXII.pdf
Creating an Uber Clone - Part XXXII.pdfCreating an Uber Clone - Part XXXII.pdf
Creating an Uber Clone - Part XXXII.pdf
 
Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Introducing the WSO2 Complex Event Processor
Introducing the WSO2 Complex Event ProcessorIntroducing the WSO2 Complex Event Processor
Introducing the WSO2 Complex Event Processor
 
Serverless stateful
Serverless statefulServerless stateful
Serverless stateful
 
CAVE Overview
CAVE OverviewCAVE Overview
CAVE Overview
 
Improving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con BerlinImproving Correctness With Type - Goto Con Berlin
Improving Correctness With Type - Goto Con Berlin
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Rajeev oops 2nd march
Rajeev oops 2nd marchRajeev oops 2nd march
Rajeev oops 2nd march
 
i want to add to this c++ code a condition so that you can only chose.docx
i want to add to this c++ code a condition so that you can only chose.docxi want to add to this c++ code a condition so that you can only chose.docx
i want to add to this c++ code a condition so that you can only chose.docx
 
ZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół ScalacZIO actors by Mateusz Sokół Scalac
ZIO actors by Mateusz Sokół Scalac
 
Serverless Stateful Architecture
Serverless Stateful ArchitectureServerless Stateful Architecture
Serverless Stateful Architecture
 
Coordinating non blocking io melb-clj
Coordinating non blocking io melb-cljCoordinating non blocking io melb-clj
Coordinating non blocking io melb-clj
 
Small pieces loosely joined
Small pieces loosely joinedSmall pieces loosely joined
Small pieces loosely joined
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developers
 
Creating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdfCreating a Facebook Clone - Part XXVI - Transcript.pdf
Creating a Facebook Clone - Part XXVI - Transcript.pdf
 
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
Open XKE - POC d'une architecture distribuée de calculs financiers par Xavier...
 

More from Roland Kuhn

Distributed systems vs compositionality
Distributed systems vs compositionalityDistributed systems vs compositionality
Distributed systems vs compositionality
Roland Kuhn
 
Reactive Design Patterns — J on the Beach
Reactive Design Patterns — J on the BeachReactive Design Patterns — J on the Beach
Reactive Design Patterns — J on the Beach
Roland Kuhn
 
The Newest in Session Types
The Newest in Session TypesThe Newest in Session Types
The Newest in Session Types
Roland Kuhn
 
Akka Streams and HTTP
Akka Streams and HTTPAkka Streams and HTTP
Akka Streams and HTTP
Roland Kuhn
 
Akka and AngularJS – Reactive Applications in Practice
Akka and AngularJS – Reactive Applications in PracticeAkka and AngularJS – Reactive Applications in Practice
Akka and AngularJS – Reactive Applications in Practice
Roland Kuhn
 
Go Reactive: Blueprint for Future Applications
Go Reactive: Blueprint for Future ApplicationsGo Reactive: Blueprint for Future Applications
Go Reactive: Blueprint for Future Applications
Roland Kuhn
 
Reactive Streams: Handling Data-Flow the Reactive Way
Reactive Streams: Handling Data-Flow the Reactive WayReactive Streams: Handling Data-Flow the Reactive Way
Reactive Streams: Handling Data-Flow the Reactive Way
Roland Kuhn
 
Akka cluster overview at 010dev
Akka cluster overview at 010devAkka cluster overview at 010dev
Akka cluster overview at 010dev
Roland Kuhn
 
Akka typed-channels
Akka typed-channelsAkka typed-channels
Akka typed-channels
Roland Kuhn
 

More from Roland Kuhn (9)

Distributed systems vs compositionality
Distributed systems vs compositionalityDistributed systems vs compositionality
Distributed systems vs compositionality
 
Reactive Design Patterns — J on the Beach
Reactive Design Patterns — J on the BeachReactive Design Patterns — J on the Beach
Reactive Design Patterns — J on the Beach
 
The Newest in Session Types
The Newest in Session TypesThe Newest in Session Types
The Newest in Session Types
 
Akka Streams and HTTP
Akka Streams and HTTPAkka Streams and HTTP
Akka Streams and HTTP
 
Akka and AngularJS – Reactive Applications in Practice
Akka and AngularJS – Reactive Applications in PracticeAkka and AngularJS – Reactive Applications in Practice
Akka and AngularJS – Reactive Applications in Practice
 
Go Reactive: Blueprint for Future Applications
Go Reactive: Blueprint for Future ApplicationsGo Reactive: Blueprint for Future Applications
Go Reactive: Blueprint for Future Applications
 
Reactive Streams: Handling Data-Flow the Reactive Way
Reactive Streams: Handling Data-Flow the Reactive WayReactive Streams: Handling Data-Flow the Reactive Way
Reactive Streams: Handling Data-Flow the Reactive Way
 
Akka cluster overview at 010dev
Akka cluster overview at 010devAkka cluster overview at 010dev
Akka cluster overview at 010dev
 
Akka typed-channels
Akka typed-channelsAkka typed-channels
Akka typed-channels
 

Recently uploaded

Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
christinelarrosa
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Neo4j
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
ScyllaDB
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
HarpalGohil4
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
Fwdays
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
Ivo Velitchkov
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
Fwdays
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
Neo4j
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
Fwdays
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
Ortus Solutions, Corp
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
christinelarrosa
 
The Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptxThe Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptx
operationspcvita
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
Neo4j
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
zjhamm304
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
leebarnesutopia
 
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
ScyllaDB
 

Recently uploaded (20)

Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 
Discover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched ContentDiscover the Unseen: Tailored Recommendation of Unwatched Content
Discover the Unseen: Tailored Recommendation of Unwatched Content
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)AWS Certified Solutions Architect Associate (SAA-C03)
AWS Certified Solutions Architect Associate (SAA-C03)
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
 
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba"NATO Hackathon Winner: AI-Powered Drug Search",  Taras Kloba
"NATO Hackathon Winner: AI-Powered Drug Search", Taras Kloba
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
 
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
"Scaling RAG Applications to serve millions of users",  Kevin Goedecke"Scaling RAG Applications to serve millions of users",  Kevin Goedecke
"Scaling RAG Applications to serve millions of users", Kevin Goedecke
 
Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!Introducing BoxLang : A new JVM language for productivity and modularity!
Introducing BoxLang : A new JVM language for productivity and modularity!
 
Christine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptxChristine's Product Research Presentation.pptx
Christine's Product Research Presentation.pptx
 
The Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptxThe Microsoft 365 Migration Tutorial For Beginner.pptx
The Microsoft 365 Migration Tutorial For Beginner.pptx
 
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge GraphGraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
GraphRAG for LifeSciences Hands-On with the Clinical Knowledge Graph
 
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...QA or the Highway - Component Testing: Bridging the gap between frontend appl...
QA or the Highway - Component Testing: Bridging the gap between frontend appl...
 
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdfLee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
Lee Barnes - Path to Becoming an Effective Test Automation Engineer.pdf
 
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's TipsGetting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
Getting the Most Out of ScyllaDB Monitoring: ShareChat's Tips
 

Taming Distribution: Formal Protocols for Akka Typed

  • 1. Taming Distribution: Formal Protocols for Akka Typed Dr. Roland Kuhn @rolandkuhn — CTO of Actyx
  • 9. Some causality comes naturally.
  • 10. Akka Typed Receptionist API trait ServiceKey[T] sealed trait Command final case class Register[T](key: ServiceKey[T], address: ActorRef[T], replyTo: ActorRef[Registered[T]]) extends Command final case class Registered[T](key: ServiceKey[T], address: ActorRef[T]) final case class Find[T](key: ServiceKey[T], replyTo: ActorRef[Listing[T]]) extends Command final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]])
  • 11. … with Unregister support trait ServiceKey[T] sealed trait Command final case class Register[T](key: ServiceKey[T], address: ActorRef[T], replyTo: ActorRef[Registered[T]]) extends Command final case class Registered[T](key: ServiceKey[T], address: ActorRef[T], handle: ActorRef[Unregister]) final case class Unregister(replyTo: ActorRef[Unregistered]) final case class Unregistered() final case class Find[T](key: ServiceKey[T], replyTo: ActorRef[Listing[T]]) extends Command final case class Listing[T](key: ServiceKey[T], addresses: Set[ActorRef[T]])
  • 12. For everything that is not fixed by causality coordination is needed.
  • 13. Static knowledge avoids coordination.
  • 15. Cluster Receptionist • use FQCN of service keys as known identifier
  • 16. Cluster Receptionist • use FQCN of service keys as known identifier • local resolution establishes static type-safety
  • 17. Cluster Receptionist • use FQCN of service keys as known identifier • local resolution establishes static type-safety • CRDT map from keys to sets of ActorRefs
  • 18. Natural causality is not enough!
  • 20. Messages for a payment system case object AuditService extends ServiceKey[LogActivity] case class LogActivity(who: ActorRef[Nothing], what: String, id: Long, replyTo: ActorRef[ActivityLogged]) case class ActivityLogged(who: ActorRef[Nothing], id: Long)
  • 21. Messages for a payment system case object AuditService extends ServiceKey[LogActivity] case class LogActivity(who: ActorRef[Nothing], what: String, id: Long, replyTo: ActorRef[ActivityLogged]) case class ActivityLogged(who: ActorRef[Nothing], id: Long) sealed trait PaymentService case class Authorize(payer: URI, amount: BigDecimal, id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Capture(id: UUID, amount: BigDecimal, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Void(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Refund(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService
  • 22. Messages for a payment system case object AuditService extends ServiceKey[LogActivity] case class LogActivity(who: ActorRef[Nothing], what: String, id: Long, replyTo: ActorRef[ActivityLogged]) case class ActivityLogged(who: ActorRef[Nothing], id: Long) sealed trait PaymentService case class Authorize(payer: URI, amount: BigDecimal, id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Capture(id: UUID, amount: BigDecimal, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Void(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService case class Refund(id: UUID, replyTo: ActorRef[PaymentResult]) extends PaymentService sealed trait PaymentResult case class PaymentSuccess(id: UUID) extends PaymentResult case class PaymentRejected(id: UUID, reason: String) extends PaymentResult case class IdUnkwown(id: UUID) extends PaymentResult
  • 23. Akka Typed crash course case class Greet(whom: String) class Greeter extends akka.actor.Actor { def receive = { case Greet(whom) => println(s"Hello $whom!") } }
  • 24. Akka Typed crash course case class Greet(whom: String) class Greeter extends akka.actor.Actor { def receive = { case Greet(whom) => println(s"Hello $whom!") } } object Greeter { import akka.typed.scaladsl.Actor val behavior = Actor.immutable[Greet] { (ctx, greet) => println(s"Hello ${greet.whom}!") Actor.same } }
  • 25. First actor: do the audit sealed trait Msg private case object AuditDone extends Msg private case object PaymentDone extends Msg private def doAudit(audit: ActorRef[LogActivity], who: ActorRef[AuditDone.type], msg: String) = Actor.deferred[ActivityLogged] { ctx => val id = Random.nextLong() audit ! LogActivity(who, msg, id, ctx.self) ctx.schedule(3.seconds, ctx.self, ActivityLogged(null, 0L)) Actor.immutable { (ctx, msg) => if (msg.who == null) throw new TimeoutException else if (msg.id != id) throw new IllegalStateException else { who ! AuditDone Actor.stopped } } }
  • 26. Second actor: do the payment private def doPayment(from: URI, amount: BigDecimal, payments: ActorRef[PaymentService], replyTo: ActorRef[PaymentDone.type]) = Actor.deferred[PaymentResult] { ctx => val uuid = UUID.randomUUID() payments ! Authorize(from, amount, uuid, ctx.self) ctx.schedule(3.seconds, ctx.self, IdUnkwown(null)) Actor.immutable { case (ctx, PaymentSuccess(`uuid`)) => payments ! Capture(uuid, amount, ctx.self) Actor.immutable { case (ctx, PaymentSuccess(`uuid`)) => replyTo ! PaymentDone Actor.stopped } // otherwise die with MatchError } }
  • 27. Third actor: orchestration of the process def getMoney[R](from: URI, amount: BigDecimal, payments: ActorRef[PaymentService], audit: ActorRef[LogActivity], replyTo: ActorRef[R], msg: R) = Actor.deferred[Msg] { ctx => ctx.watch(ctx.spawn(doAudit(audit, ctx.self, "starting payment"), "preAudit")) Actor.immutable[Msg] { case (ctx, AuditDone) => ctx.watch(ctx.spawn(doPayment(from, amount, payments, ctx.self), "payment")) Actor.immutable[Msg] { case (ctx, PaymentDone) => ctx.watch(ctx.spawn(doAudit(audit, ctx.self, "payment finished"), "postAudit")) Actor.immutable[Msg] { case (ctx, AuditDone) => replyTo ! msg Actor.stopped } } onSignal terminateUponChildFailure } onSignal terminateUponChildFailure }
  • 28. code can employ knowledge in wrong order or existing knowledge is not used at all
  • 29. What if we prescribe effects and their order?
  • 30. Which steps shall be done? • send audit log, get confirmation for that • send Authorize request, get confirmation • send Capture request, get confirmation • send audit log, get confirmation
  • 31. Akka Typed Session: protocol definition object GetMoneyProtocol extends Protocol { type Session = // Send[LogActivity] :: // preAudit Read[ActivityLogged] :: // Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate Send[Authorize] :: // do payment Read[PaymentResult] :: // Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate Send[Capture] :: // Read[PaymentResult] :: // Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate Send[LogActivity] :: // postAudit Read[ActivityLogged] :: // Choice[(Halt :: _0) :+: _0 :+: CNil] :: // possibly terminate _0 }
  • 32. First process: do the audit private def doAudit(audit: ActorRef[LogActivity], who: ActorRef[Nothing], msg: String) = OpDSL[ActivityLogged] { implicit opDSL => val id = Random.nextLong() for { self <- opProcessSelf _ <- opSend(audit, LogActivity(who, msg, id, self)) ActivityLogged(`who`, `id`) <- opRead } yield Done }.withTimeout(3.seconds) /* * the return type is * Process[ActivityLogged, Done, * Send[LogActivity] :: Read[ActivityLogged] :: * Choice[(Halt :: _0) :+: _0 :+: CNil] :: _0] */
  • 33. Second process: do the payment private def doPayment(from: URI, amount: BigDecimal, payments: ActorRef[PaymentService]) = OpDSL[PaymentResult] { implicit opDSL => val uuid = UUID.randomUUID() for { self <- opProcessSelf _ <- opSend(payments, Authorize(from, amount, uuid, self)) PaymentSuccess(`uuid`) <- opRead _ <- opSend(payments, Capture(uuid, amount, self)) PaymentSuccess(`uuid`) <- opRead } yield Done }.withTimeout(3.seconds) /* * the return type is * Process[PaymentResult, Done, * Send[Authorize] :: Read[PaymentResult] :: * Choice[(Halt :: _0) :+: _0 :+: CNil] :: * Send[Capture] :: Read[PaymentResult] :: * Choice[(Halt :: _0) :+: _0 :+: CNil] :: _0] */
  • 34. Third process: orchestrate and verify // this useful process is provided by the Session DSL and talks to the Receptionist def getService[T](key: ServiceKey[T]): Operation[Listing[T], ActorRef[T], _0] def getMoney[R](from: URI, amount: BigDecimal, payments: ActorRef[PaymentService], replyTo: ActorRef[R], msg: R) = OpDSL[Nothing] { implicit opDSL => for { self <- opProcessSelf audit <- opCall(getService(AuditService) .named("getAuditService")) _ <- opCall(doAudit(audit, self, "starting payment").named("preAudit")) _ <- opCall(doPayment(from, amount, payments) .named("payment")) _ <- opCall(doAudit(audit, self, "payment finished").named("postAudit")) } yield replyTo ! msg }
  • 35. Third process: orchestrate and verify // this useful process is provided by the Session DSL and talks to the Receptionist def getService[T](key: ServiceKey[T]): Operation[Listing[T], ActorRef[T], _0] def getMoney[R](from: URI, amount: BigDecimal, payments: ActorRef[PaymentService], replyTo: ActorRef[R], msg: R) = OpDSL[Nothing] { implicit opDSL => for { self <- opProcessSelf audit <- opCall(getService(AuditService) .named("getAuditService")) _ <- opCall(doAudit(audit, self, "starting payment").named("preAudit")) _ <- opCall(doPayment(from, amount, payments) .named("payment")) _ <- opCall(doAudit(audit, self, "payment finished").named("postAudit")) } yield replyTo ! msg } // compile-time verification (TODO: should be a macro) private def verify = E.vetExternalProtocol(GetMoneyProtocol, getMoney(???, ???, ???, ???, ???))
  • 36. Conclusion: There is a lot on the table, get involved! https://github.com/rkuhn/akka-typed-session