DDDing Tools = Akka Persistence
-
Upload
konrad-malawski -
Category
Technology
-
view
3.524 -
download
5
description
Transcript of DDDing Tools = Akka Persistence
![Page 1: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/1.jpg)
DDDing with Akka Persistence !
Konrad 'ktoso' Malawski GeeCON 2014 @ Kraków, PL
Konrad `@ktosopl` Malawski
![Page 2: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/2.jpg)
Konrad `@ktosopl` Malawski
hAkker @
![Page 3: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/3.jpg)
Konrad `@ktosopl` Malawski
typesafe.com geecon.org
Java.pl / KrakowScala.pl sckrk.com / meetup.com/Paper-Cup @ London
GDGKrakow.pl meetup.com/Lambda-Lounge-Krakow
hAkker @
![Page 4: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/4.jpg)
mainly by Martin Krasser !!(as contractor for Typesafe) !inspired by:
https://github.com/krasserm
https://github.com/eligosource/eventsourced
akka-persistence
![Page 5: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/5.jpg)
Dependencies
libraryDependencies ++= Seq(! "com.typesafe.akka" %% “akka-actor" % "2.3.1",! "com.typesafe.akka" %% "akka-persistence-experimental" % "2.3.1"!)
![Page 6: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/6.jpg)
Show of hands!
![Page 7: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/7.jpg)
Show of hands!
![Page 8: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/8.jpg)
Show of hands!
![Page 9: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/9.jpg)
Show of hands!
![Page 10: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/10.jpg)
sourcing styles
Command Sourcing Event Sourcing
msg: DoThing
msg persisted before receive
imperative, “do the thing”
business logic change, can be reflected in reaction
Processor
![Page 11: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/11.jpg)
sourcing styles
Command Sourcing Event Sourcing
msg: DoThing msg: ThingDone
msg persisted before receive commands converted to events, must be manually persisted
imperative, “do the thing” past tense, “happened”
business logic change, can be reflected in reaction
business logic change, won’t change previous events
Processor EventsourcedProcessor
![Page 12: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/12.jpg)
Compared to “Good ol’ CRUD Model”
state
“Mutable Record”
state =
apply(es)
“Series of Events”
![Page 13: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/13.jpg)
Actors
![Page 14: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/14.jpg)
count: 0 !
!
Actor
An Actor that keeps count of messages it processed !
Let’s send 2 messages to it (it’s “commands”)
![Page 15: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/15.jpg)
Actor
!!class Counter extends Actor {! var count = 0! def receive = {! case _ => count += 1! }!}
![Page 16: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/16.jpg)
count: 0 !
!
Actor
![Page 17: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/17.jpg)
count: 0 !
!
Actor
![Page 18: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/18.jpg)
count: 1 !
!
Actor
crash!
![Page 19: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/19.jpg)
Actor
crash!
![Page 20: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/20.jpg)
Actor
restart
![Page 21: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/21.jpg)
count: 0 !
!
Actor
restart
![Page 22: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/22.jpg)
count: 0 !
!
Actor
restarted
![Page 23: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/23.jpg)
count: 1 !
!
Actor
restarted
![Page 24: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/24.jpg)
count: 1 !
!wrong!
expected count == 2!
Actor
restarted
![Page 25: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/25.jpg)
Consistency Boundary
![Page 26: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/26.jpg)
Consistency Boundary equals Async Boundary
![Page 27: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/27.jpg)
Boundaries
actor
actor
async
![Page 28: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/28.jpg)
Boundaries
aggregate
aggregate
“eventual”
A.K.A. async
![Page 29: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/29.jpg)
Business rules
aggregate
Any rule that spans AGGREGATES will not be expected to be up-to-date at all times. Through event processing, batch processing, or
other update mechanisms, other dependencies can be resolved within some specific time. [Evans, p. 128]
aggregate
consistentconsistent
eventually consistent
![Page 30: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/30.jpg)
Let’s open the toolbox
![Page 31: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/31.jpg)
Processor
![Page 32: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/32.jpg)
Processor (command sourcing)
![Page 33: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/33.jpg)
var count = 0 !
def processorId = “a” !
Journal (DB)
!
!
!
Processor
![Page 34: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/34.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
![Page 35: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/35.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
![Page 36: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/36.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
![Page 37: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/37.jpg)
Journal (DB)
!
!
!
Processor
var count = 1 !
def processorId = “a” !
![Page 38: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/38.jpg)
Journal (DB)
!
!
!
Processor
var count = 1 !
def processorId = “a” !
crash!
![Page 39: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/39.jpg)
Journal (DB)
!
!
!
Processor
restart
![Page 40: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/40.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
restart
![Page 41: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/41.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
replay!
restart
![Page 42: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/42.jpg)
Journal (DB)
!
!
!
Processor
var count = 0 !
def processorId = “a” !
replay!
![Page 43: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/43.jpg)
Journal (DB)
!
!
!
Processor
var count = 1 !
def processorId = “a” !
replay!
![Page 44: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/44.jpg)
Journal (DB)
!
!
!
Processor
var count = 1 !
def processorId = “a” !
![Page 45: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/45.jpg)
Journal (DB)
!
!
!
Processor
var count = 2 !
def processorId = “a” !
yay!
![Page 46: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/46.jpg)
Processor
import akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // payload already persisted! count += 1! }!}
![Page 47: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/47.jpg)
Processor
import akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // payload already persisted! count += 1! }!}
counter ! Persistent(payload)
![Page 48: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/48.jpg)
Processor
import akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // payload already persisted! count += 1! }!}
counter ! Persistent(payload)
![Page 49: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/49.jpg)
Processor
import akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // payload already persisted! count += 1! }!}
counter ! Persistent(payload)
sequenceNr (generated by akka)
is already persisted!
![Page 50: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/50.jpg)
Processor
import akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case notPersisted: Event =>! // will not replay this msg!! count += 1! }!}
counter ! payload
won’t persist
won’t replay
![Page 51: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/51.jpg)
Processorimport akka.persistence._!!class CounterProcessor extends Processor {! var count = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // payload already persisted! count += 1!! case notPersistentMsg =>! // msg not persisted - like in normal Actor! count += 1! }!}
![Page 52: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/52.jpg)
Processor
Upsides
• Persistent Command Sourcing “out of the box”
• Pretty simple, persist handled for you
• Once you get the msg, it’s persisted
• Pluggable Journals (HBase, Cassandra, Mongo, …)
• Can replay to given seqNr (post-mortem etc!)
![Page 53: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/53.jpg)
Processor
Downsides
• Exposes Persistent() to Actors who talk to you
• No room for validation before persisting
• There’s one Model, we act on the incoming msg
• Lower throughput than plain Actor (limited by DB)
![Page 54: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/54.jpg)
Eventsourced Processor
![Page 55: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/55.jpg)
Eventsourced Processor (event sourcing)
![Page 56: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/56.jpg)
super quick domain modeling!
sealed trait Command!case class GiveMe(geeCoins: Int) extends Command!case class TakeMy(geeCoins: Int) extends Command
Commands - what others “tell” us; not persisted
case class Wallet(geeCoins: Int) {! def updated(diff: Int) = State(geeCoins + diff)!}
State - reflection of a series of events
sealed trait Event!case class BalanceChangedBy(geeCoins: Int) extends Event!
Events - reflect effects, past tense; persisted
![Page 57: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/57.jpg)
var state = S0 !
def processorId = “a” !
EventsourcedProcessor
Command
!
!
Journal
![Page 58: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/58.jpg)
EventsourcedProcessor
var state = S0 !
def processorId = “a” !
!
!
Journal
Generate Events
![Page 59: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/59.jpg)
EventsourcedProcessor
var state = S0 !
def processorId = “a” !
!
!
Journal
Generate Events
E1
![Page 60: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/60.jpg)
EventsourcedProcessor
ACK “persisted”
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
![Page 61: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/61.jpg)
EventsourcedProcessor
“Apply” event
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
E1
![Page 62: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/62.jpg)
EventsourcedProcessor
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
E1
Okey!
![Page 63: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/63.jpg)
EventsourcedProcessor
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
E1
Okey!
![Page 64: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/64.jpg)
EventsourcedProcessor
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
E1
Ok, he got my $.
![Page 65: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/65.jpg)
EventsourcedProcessor
class GeeCoinWallet extends EventsourcedProcessor {!! var state = Wallet(geeCoins = 0)!! def updateState(e: Event): State = {! case BalanceChangedBy(geeCoins) => state updated geeCoins! }! ! // API:!! def receiveCommand = ??? // TODO!! def receiveRecover = ??? // TODO!!}!
![Page 66: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/66.jpg)
EventsourcedProcessor
def receiveCommand = {!! case TakeMy(geeCoins) =>! persist(BalanceChangedBy(geeCoins)) { changed =>! state = updateState(changed) ! }!!!!!!!}
async callback
![Page 67: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/67.jpg)
EventsourcedProcessor
def receiveCommand = {!!!!!!! case GiveMe(geeCoins) if geeCoins <= state.geeCoins =>! persist(BalanceChangedBy(-geeCoins)) { changed =>! state = updateState(changed) ! sender() ! TakeMy(-geeCoins)! }!}
Safe to access sender here
async callback
![Page 68: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/68.jpg)
EventsourcedProcessor
def receiveCommand = {!!!!!!! case GiveMe(geeCoins) if geeCoins <= state.geeCoins =>! persist(BalanceChangedBy(-geeCoins)) { changed =>! state = updateState(changed) ! sender() ! TakeMy(-geeCoins)! }!}
Is this safe? It’s async! Races?!
![Page 69: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/69.jpg)
Ordering guarantees
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
C1C2
C3
![Page 70: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/70.jpg)
Ordering guarantees
!
!
Journal
E1
var state = S0 !
def processorId = “a” !
C1C2
C3
Commands get “stashed” until processing C1’s events are acted upon.
![Page 71: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/71.jpg)
!
!
Journal
Ordering guarantees
var state = S0 !
def processorId = “a” !
C1C2
C3 E1
E2
E2E1
events get applied in-order
![Page 72: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/72.jpg)
C2
!
!
Journal
Ordering guarantees
var state = S0 !
def processorId = “a” !
C3 E1 E2
E2E1
and the cycle repeats
![Page 73: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/73.jpg)
Eventsourced, recovery
/** MUST NOT SIDE-EFFECT! */!def receiveRecover = {! case replayedEvent: Event => ! updateState(replayedEvent)!}
exact same code for all events!
![Page 74: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/74.jpg)
Snapshots
![Page 75: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/75.jpg)
Snapshots (in SnapshotStore)
![Page 76: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/76.jpg)
Eventsourced, snapshots
def receiveCommand = {! case command: Command =>! saveSnapshot(state) // async!!}
/** MUST NOT SIDE-EFFECT! */!def receiveRecover = {! case SnapshotOffer(meta, snapshot: State) => ! this.state = state!! case replayedEvent: Event => ! updateState(replayedEvent)!}
snapshot!? how?
![Page 77: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/77.jpg)
…sum of states…
Snapshots
!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
![Page 78: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/78.jpg)
state until [E8]
Snapshots
S8
!
!
Snapshot Store
snapshot!
!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
![Page 79: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/79.jpg)
state until [E8]
Snapshots
S8
!
!
Snapshot Store
!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
S8
crash!
![Page 80: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/80.jpg)
Snapshots
!
!
Snapshot Store
!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
S8
crash!
![Page 81: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/81.jpg)
“bring me up-to-date!”
Snapshots
!
!
Snapshot Store
!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
S8
restart!replay!
![Page 82: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/82.jpg)
“bring me up-to-date!”
Snapshots
!
!
Snapshot Store
S8
restart!replay!
S8!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
![Page 83: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/83.jpg)
state until [E8]
Snapshots
!
!
Snapshot Store
S8
restart!replay!
S8!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
![Page 84: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/84.jpg)
state until [E8]
Snapshots
!
!
Snapshot Store
S8
S8!
!
Journal
E1 E2 E3 E4
E5 E6 E7 E8
We could delete these!
![Page 85: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/85.jpg)
trait MySummer extends Processor {! var nums: List[Int]! var total: Int! ! def receive = {! case "snap" => saveSnapshot(total)! case SaveSnapshotSuccess(metadata) => // ...! case SaveSnapshotFailure(metadata, reason) => // ...! }!}!
Snapshots, save
Async!
![Page 86: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/86.jpg)
trait MySummer extends Processor {! var nums: List[Int]! var total: Int! ! def receive = {! case "snap" => saveSnapshot(total)! case SaveSnapshotSuccess(metadata) => // ...! case SaveSnapshotFailure(metadata, reason) => // ...! }!}!
Snapshots, success
final case class SnapshotMetadata(! processorId: String, sequenceNr: Long, ! timestamp: Long)
![Page 87: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/87.jpg)
trait MySummer extends Processor {! var nums: List[Int]! var total: Int! ! def receive = {! case "snap" => saveSnapshot(total)! case SaveSnapshotSuccess(metadata) => // ...! case SaveSnapshotFailure(metadata, reason) => // ...! }!}!
Snapshots, success
![Page 88: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/88.jpg)
Snapshot Recovery
class Counter extends Processor {! var total = 0! ! def receive = {! case SnapshotOffer(metadata, snap: Int) => ! total = snap!! case Persistent(payload, sequenceNr) => // ...! }!}
![Page 89: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/89.jpg)
Snapshots
Upsides
• Simple!
• Faster recovery (!)
• Allows to delete “older” events
• “known state at point in time”
![Page 90: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/90.jpg)
Snapshots
Downsides
• More logic to write
• Maybe not needed if events replay “fast enough”
• Possibly “yet another database” to pick
• snapshots are different than events, may be big!
![Page 91: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/91.jpg)
Views
![Page 92: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/92.jpg)
Journal (DB)
!
!
!
Views
!Processor
!def processorId = “a”
!
!View
!def processorId = “a”
!!!
pooling
![Page 93: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/93.jpg)
Journal (DB)
!
!
!
Views
!Processor
!def processorId = “a”
!
!View
!def processorId = “a”
!!!
pooling
!View
!def processorId = “a”
!!!
pooling
different ActorPath, same processorId
![Page 94: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/94.jpg)
View
class DoublingCounterProcessor extends View {! var state = 0! override val processorId = "counter"!! def receive = {! case Persistent(payload, seqNr) =>! // “state += 2 * payload” !! }!}
![Page 95: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/95.jpg)
Akka Persistence Plugins
Plugins are Community maintained! (“not sure how production ready”)
http://akka.io/community/#journal_plugins
!
• Journals - Cassandra, HBase, Mongo …
• SnapshotStores - Cassandra, HDFS, HBase, Mongo …
![Page 96: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/96.jpg)
SnapshotStore Plugins!
http://akka.io/community/#journal_plugins
![Page 97: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/97.jpg)
Extra: Channels
![Page 98: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/98.jpg)
Extras: Channel
Features:
• de-duplication
![Page 99: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/99.jpg)
Extras: PersistentChannel
Features:
• “at least once delivery”
![Page 100: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/100.jpg)
Try it now
![Page 101: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/101.jpg)
Try it now() // !
typesafe.com/activator
akka-sample-persistence-scala
![Page 102: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/102.jpg)
Links
• Official docs: http://doc.akka.io/docs/akka/2.3.0/scala/persistence.html
• Patrik’s Slides & Webinar: http://www.slideshare.net/patriknw/akka-persistence-webinar
• Papers:
• Sagas http://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
• Life beyond Distributed Transactions: http://www-db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf
• Pics:
• http://misaspuppy.deviantart.com/art/Messenger-s-Cutie-Mark-A-Flying-Envelope-291040459
![Page 103: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/103.jpg)
Mailing List
groups.google.com/forum/#!forum/akka-user
![Page 104: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/104.jpg)
Links
Eric Evans: "The DDD book”
Talk: “Acknowledging CAP at the Root” !!!!!!
Vaughn Vernon’s Book and Talk !!
![Page 105: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/105.jpg)
ktoso @ typesafe.com twitter: ktosopl github: ktoso blog: project13.pl team blog: letitcrash.com GeeCON 2014 @ Kraków, PL
!
Dzięki! Thanks! ありがとう! !
!
ping me:
![Page 106: DDDing Tools = Akka Persistence](https://reader030.fdocuments.net/reader030/viewer/2022013121/554bbbfab4c90530298b4cc0/html5/thumbnails/106.jpg)
©Typesafe 2014 – All Rights Reserved