SlideShare a Scribd company logo
1 of 54
Download to read offline
Akka Persistence Webinar
by Patrik Nordwall

@patriknw
opt-in at-least-once delivery
semantics between actors
recover application state after a crash
Akka 2.3.0 Release


"com.typesafe.akka" %% "akka-persistence-experimental" % "2.3.0"

<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-persistence-experimental_2.10</artifactId>
<version>2.3.0</version>
</dependency>
Martin Krasser

Twitter: mrt1nz

Github: krasserm
Eventsourced



akka-persistence

September 2013 - February 2014 

contractor for Typesafe
Awesome work, Martin!
storing structure
*
Purchase
Order
Line Item
Shipping
Information
storing state transitions
Cart
Created
Added 2
Socks
Added 2
Shirts
Shipping
Info Added
Akka  Persistence  Webinar
Domain Events
• things that have completed, facts
• immutable
• verbs in past tense
• CustomerRelocated
• CargoShipped
• InvoiceSent
“State transitions are an important part of our problem
space and should be modeled within our domain.”  
Greg Young, 2008
Akka  Persistence  Webinar
Benefits
• Bullet-proof auditing and historical tracing
• Support future ways of looking at data
• Performance and scalability
• Testability
• Reconstruct production scenarios
• No object-relational impedance mismatch
• Nice fit with actors
Akka  Persistence  Webinar
Command Sourcing Event Sourcing
write-ahead-log derive events from a command
same behavior during recovery as
normal operation
external interaction can be problematic
only state-changing behavior during
recovery
persisted before validation events cannot fail
allows retroactive changes to the
business logic
fixing the business logic will not
affect persisted events
naming: represent intent, imperative naming: things that have completed,
verbs in past tense
Akka  Persistence  Webinar
Consistency boundary
• An actor is a consistency boundary
• DDD Aggregate
• No distributed transactions
• eventually consistent
• compensating actions
Akka  Persistence  Webinar
Life beyond Distributed Transactions:
an Apostate’s Opinion
Position Paper
Pat Helland
“In general, application developers simply do not implement
large scalable applications assuming distributed transactions.”  
Pat Helland
http://www-­‐db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf
Processor
Eventsourced

Processor
Channel
Persistent

Channel
View
Journal
Cluster

Sharding
Building Blocks
Processor
import akka.persistence.{ Persistent, Processor }
!
class MyProcessor extends Processor {
def receive = {
case Persistent(payload, sequenceNr) =>
// message successfully written to journal
case other =>
// message not written to journal
}
}
val processor = context.actorOf(Props[MyProcessor],

name = "myProcessor")
!
processor ! Persistent("foo") // will be journaled
processor ! "bar" // will not be journaled
Processor
class InvoiceService extends Processor {
var invoices = Map.empty[String, Invoice]
!
def receive: Receive = {
case Persistent(CreateInvoice(id), _) =>
invoices = invoices.updated(id, Invoice(id))
}
}
Processor
class InvoiceService extends Processor {
var invoices = Map.empty[String, Invoice]
!
def receive: Receive = {
case Persistent(CreateInvoice(id), _) =>
invoices = invoices.updated(id, Invoice(id))
!
case Persistent(AddInvoiceItem(id, item), _) =>
invoices.get(id) match {
case Some(inv) =>
invoices = invoices.updated(id, inv.addItem(item))
case None => // TODO
}
!
case GetInvoice(id) =>
sender() ! invoices.getOrElse(id, "not found: " + id)
!
case Persistent(SendInvoiceTo(id, address), _) =>
// TODO send to the invoice printing service
}
}
Processor
case class CreateInvoice(invoiceId: String)
case class AddInvoiceItem(invoiceId: String, invoiceItem: InvoiceItem)
case class SendInvoiceTo(invoiceId: String, to: InvoiceAddress)
case class GetInvoice(invoiceId: String)
!
case class Invoice(id: String,
items: IndexedSeq[InvoiceItem] = Vector.empty) {
def addItem(item: InvoiceItem): Invoice =
copy(items = items :+ item)
}
!
case class InvoiceItem(description: String, count: Int,
amount: BigDecimal)
!
case class InvoiceAddress(name: String, street: String, city: String)
Processor Identifier


override def processorId = "my-stable-processor-id"
Default is actor path without address

/user/top/myProcessor
Don’t use anonymous processors
Akka  Persistence  Webinar
Processor
• Automatic recovery on start and restart
• Stashing until recovery completed
• Failure handling with supervisor strategy
• Might want to delete erroneous messages
What about side effects during replay?
Processor with Channel
val printingChannel = context.actorOf(Channel.props(),
name = "printingChannel")
val printingDestination = context.system / "printingService"
!
def receive: Receive = {
case p @ Persistent(SendInvoiceTo(id, address), _) =>
// send to the invoice printing service
invoices.get(id) match {
case Some(inv) =>
printingChannel ! Deliver(p.withPayload(
PrintingOrder(inv, address)), printingDestination)
invoices -= inv.id
case None => // TODO
}
}
class PrintingService extends Actor {
def receive = {
case p @ ConfirmablePersistent(payload, sequenceNr, redeliveries) =>
// ...
p.confirm()
}
}
Akka  Persistence  Webinar
EventsourcedProcessor
• Incoming messages (commands) are not persisted
• Steps:
1. Validate command
2. Create domain event and explicitly persist it
3. Update internal state, by applying the event
4. External side effects
• During recovery the internal state is updated by applying the events
• no external side effects
EventsourcedProcessor
class BlogPost extends EventsourcedProcessor {
override def receiveCommand: Receive = ???

override def receiveRecover: Receive = ???
}
EventsourcedProcessor
object BlogPost {
case class AddPost(author: String, title: String)
}
!
class BlogPost extends EventsourcedProcessor {
override def receiveCommand: Receive = ???

override def receiveRecover: Receive = ???
}
object BlogPost {
case class AddPost(author: String, title: String)
}
!
class BlogPost extends EventsourcedProcessor {
import BlogPost._
!
override def receiveCommand: Receive = {
case AddPost(author, title) =>
persist(PostAdded(author, title)) { evt =>
state = state.updated(evt)
}
}
!
override def receiveRecover: Receive = ???
}
EventsourcedProcessor
EventsourcedProcessor
object BlogPost {
case class AddPost(author: String, title: String)
!
sealed trait Event
case class PostAdded(author: String, title: String) extends Event
!
private case class State(author: String, title: String) {
def updated(evt: Event): State = evt match {
case PostAdded(author, title) => copy(author, title)
}
}
}
!
class BlogPost extends EventsourcedProcessor {
import BlogPost._
private var state = State("", “")
!
override def receiveCommand: Receive = {
case AddPost(author, title) =>
persist(PostAdded(author, title)) { evt =>
state = state.updated(evt)
}
}
!
override def receiveRecover: Receive = ???
}
EventsourcedProcessor
object BlogPost {
case class AddPost(author: String, title: String)
case class ChangeBody(body: String)
case object Publish
!
sealed trait Event
case class PostAdded(author: String, title: String) extends Event
case class BodyChanged(body: String) extends Event
case object PostPublished extends Event
!
private case class State(author: String, title: String,
body: String, published: Boolean) {
!
def updated(evt: Event): State = evt match {
case PostAdded(author, title) => copy(author, title)
case BodyChanged(b) => copy(body = b)
case PostPublished => copy(published = true)
}
}
}
EventsourcedProcessor
class BlogPost extends EventsourcedProcessor {
import BlogPost._
private var state = State("", "", "", false)
!
override def receiveCommand: Receive = {
case AddPost(author, title) =>
if (state.body == "" && author != "" && title != "")
persist(PostAdded(author, title)) { evt =>
state = state.updated(evt)
}
case ChangeBody(body) =>
if (!state.published)
persist(BodyChanged(body)) { evt =>
state = state.updated(evt)
}
case Publish =>
if (!state.published)
persist(PostPublished) { evt =>
state = state.updated(evt)
// call external web content service ...
}
}
!
override def receiveRecover: Receive = {
case evt: Event => state = state.updated(evt)
}
}
Snapshots
class MyProcessor extends Processor {
var state: Any = _
def receive = {
case "snap" => saveSnapshot(state)
case SaveSnapshotSuccess(metadata) => // ...
case SaveSnapshotFailure(metadata, reason) => // ...
}
}
Snapshots
class MyProcessor extends Processor {
var state: Any = _
def receive = {
case "snap" => saveSnapshot(state)
case SaveSnapshotSuccess(metadata) => // ...
case SaveSnapshotFailure(metadata, reason) => // ...
!
case SnapshotOffer(metadata, offeredSnapshot) => state = offeredSnapshot
case Persistent(payload, _) => // ...
}
}
Akka  Persistence  Webinar
View
• replays Persistent messages from a Processor’s journal
• query side of CQRS
• features
• auto-update interval
• Update message
• limit
• may store its own snapshots
View
class InvoiceCounter extends View {
import InvoiceCounter._
override def processorId: String = "/user/invoiceService"
override def autoUpdateInterval = 10.seconds
!
var count = 0L
!
def receive: Actor.Receive = {
case Persistent(payload: SendInvoiceTo, _) =>
count += 1
case _: Persistent =>
case GetInvoiceCount =>
sender ! InvoiceCount(count)
}
}
!
object InvoiceCounter {
case object GetInvoiceCount
case class InvoiceCount(count: Long)
}
Processor
Eventsourced

Processor
Channel
Persistent

Channel
View
Journal
Cluster

Sharding
Building Blocks
Akka  Persistence  Webinar
At-least-once delivery
sender destination
$
Akka  Persistence  Webinar
At-least-once delivery
sender destination
$
ok
$
ok
Akka  Persistence  Webinar
Channels
• re-deliver messages until confirmed
• application level confirmation
• different semantics
• duplicates may be received
• message order not retained
• after a crash and restart messages are still delivered
• listener for RedeliverFailure notifications
• recommendation: one destination per channel 

exception: replies via channel
Akka  Persistence  Webinar
Channel vs. PersistentChannel
• Channel
• use from Processor
• in-memory
• PersistentChannel
• standalone usage
• conceptually: processor + channel
• persist messages before delivering
• reply ack when persisted
• more advanced delivery flow control
Processor with Channel
class MyProcessor extends Processor {
val channel = context.actorOf(Channel.props(), name = "myChannel")
!
def receive = {
case p @ Persistent(payload, _) =>
val destination = context.system / "myDestination"
channel ! Deliver(p.withPayload("output msg"), destination)
}
}
!
class MyDestination extends Actor {
def receive = {
case p @ ConfirmablePersistent(payload, sequenceNr, redeliveries) =>
// ...
p.confirm()
}
}
PersistentChannel
class Endpoint extends Actor {
val channel = context.actorOf(PersistentChannel.props(
PersistentChannelSettings(redeliverInterval = 3.seconds, redeliverMax = 10,
replyPersistent = true)), name = "myChannel")
val destination = context.system / "jobManager"
!
import context.dispatcher
implicit val timeout = Timeout(5.seconds)
!
def receive = {
case job: Job =>
(channel ? Deliver(Persistent(job), destination)) map {
case _: Persistent => "OK: " + job.id
} recover {
case e => "FAILED: " + job.id
} pipeTo sender()
}
}
Akka  Persistence  Webinar
Serialization
• pluggable, Akka serialization
• application life-cycle, versioning
• don’t use default Java serialization
Akka  Persistence  Webinar
Journal and snapshot store
• pluggable
• LevelDB shipped with Akka – local files
• Community http://akka.io/community/
• BDB
• Cassandra
• DynamoDB
• HBase
• MapDB
• MongoDB
Akka  Persistence  Webinar
Cluster
• simple way of migrating/moving stateful actors in a cluster
• distributed journal
• shared LevelDB journal for testing
• single writer per event stream
• cluster singleton
• cluster sharding
Akka  Persistence  Webinar
Cluster Singleton
A
B
C D
Akka  Persistence  Webinar
Cluster Singleton
A
B
C
D
role: backend-1 role: backend-1
role: backend-2 role: backend-2
Akka  Persistence  Webinar
Cluster Sharding
A B
C D
Akka  Persistence  Webinar
Cluster Sharding
sender
id:17
region

node-­‐1
coordinator
region

node-­‐2
region

node-­‐3
GetShardHome:17
id:17 ShardHome:17  -­‐>  node2
17  -­‐>  node2
Akka  Persistence  Webinar
Cluster Sharding
sender region

node-­‐1
coordinator
region

node-­‐2
region

node-­‐3
id:17
id:17
GetShardHome:17
ShardHome:17  -­‐>  node2
id:17
17  -­‐>  node2
17  -­‐>  node2
Akka  Persistence  Webinar
Cluster Sharding
17
sender region

node-­‐1
coordinator
region

node-­‐2
region

node-­‐3
id:17
id:17
17  -­‐>  node2
17  -­‐>  node2
17  -­‐>  node2
Akka  Persistence  Webinar
Cluster Sharding
17
sender region

node-­‐1
coordinator
region

node-­‐2
region

node-­‐3
17  -­‐>  node2
17  -­‐>  node2
17  -­‐>  node2
id:17
Akka  Persistence  Webinar
Cluster Sharding
17
sender region

node-­‐1
coordinator
region

node-­‐2
region

node-­‐3
17  -­‐>  node2
17  -­‐>  node2
17  -­‐>  node2
id:17
Cluster Sharding
val idExtractor: ShardRegion.IdExtractor = {
case cmd: Command => (cmd.postId, cmd)
}
!
val shardResolver: ShardRegion.ShardResolver = msg => msg match {
case cmd: Command => (math.abs(cmd.postId.hashCode) % 100).toString
}
ClusterSharding(system).start(
typeName = BlogPost.shardName,
entryProps = Some(BlogPost.props()),
idExtractor = BlogPost.idExtractor,
shardResolver = BlogPost.shardResolver)
val postRegion: ActorRef = 

ClusterSharding(context.system).shardRegion(BlogPost.shardName)
!
val postId = UUID.randomUUID().toString
postRegion ! BlogPost.AddPost(postId, author, title)
Processor
Eventsourced

Processor
Channel
Persistent

Channel
View
Journal
Cluster

Sharding
Building Blocks
Akka  Persistence  Webinar
Next step
• Documentation
• http://doc.akka.io/docs/akka/2.3.0/scala/persistence.html
• http://doc.akka.io/docs/akka/2.3.0/java/persistence.html
• http://doc.akka.io/docs/akka/2.3.0/contrib/cluster-sharding.html
• Typesafe Activator
• https://typesafe.com/activator/template/akka-sample-persistence-scala
• https://typesafe.com/activator/template/akka-sample-persistence-java
• http://typesafe.com/activator/template/akka-cluster-sharding-scala
• Mailing list
• http://groups.google.com/group/akka-user
• Migration guide from Eventsourced
• http://doc.akka.io/docs/akka/2.3.0/project/migration-guide-eventsourced-2.3.x.html
Akka  Persistence  Webinar
Akka in Action
• All registrants for this webinar qualify for a free E-Book PDF subset of
Akka in Action by Raymond Roestenburg, Rob Bakker and Rob Williams.
Additionally, you will qualify for the Typesafe discount and can save 40%
on the full book.
©Typesafe 2014 – All Rights Reserved

More Related Content

What's hot

Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Konrad Malawski
 

What's hot (20)

Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"Distributed Consensus A.K.A. "What do we eat for lunch?"
Distributed Consensus A.K.A. "What do we eat for lunch?"
 
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka StreamsFresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
 
A Crash Course on Serverless Applications in Python
A Crash Course on Serverless Applications in PythonA Crash Course on Serverless Applications in Python
A Crash Course on Serverless Applications in Python
 
Building an aws sdk for Perl - Granada Perl Workshop 2014
Building an aws sdk for Perl - Granada Perl Workshop 2014Building an aws sdk for Perl - Granada Perl Workshop 2014
Building an aws sdk for Perl - Granada Perl Workshop 2014
 
Webinar - How to Build Data Pipelines for Real-Time Applications with SMACK &...
Webinar - How to Build Data Pipelines for Real-Time Applications with SMACK &...Webinar - How to Build Data Pipelines for Real-Time Applications with SMACK &...
Webinar - How to Build Data Pipelines for Real-Time Applications with SMACK &...
 
CLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.jsCLS & asyncListener: asynchronous observability for Node.js
CLS & asyncListener: asynchronous observability for Node.js
 
Device Simulator with Akka
Device Simulator with AkkaDevice Simulator with Akka
Device Simulator with Akka
 
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
 
The dark side of Akka and the remedy
The dark side of Akka and the remedyThe dark side of Akka and the remedy
The dark side of Akka and the remedy
 
Reactive stream processing using Akka streams
Reactive stream processing using Akka streams Reactive stream processing using Akka streams
Reactive stream processing using Akka streams
 
Next generation actors with Akka
Next generation actors with AkkaNext generation actors with Akka
Next generation actors with Akka
 
Streaming all the things with akka streams
Streaming all the things with akka streams   Streaming all the things with akka streams
Streaming all the things with akka streams
 
Reactive streams processing using Akka Streams
Reactive streams processing using Akka StreamsReactive streams processing using Akka Streams
Reactive streams processing using Akka Streams
 
Networks and types - the future of Akka
Networks and types - the future of AkkaNetworks and types - the future of Akka
Networks and types - the future of Akka
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile Apps
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconf
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 

Viewers also liked

Akka Http , Routes, Streams with Scala
Akka Http , Routes, Streams with ScalaAkka Http , Routes, Streams with Scala
Akka Http , Routes, Streams with Scala
Jerry Kuru
 

Viewers also liked (20)

Akka Persistence and Eventuate
Akka Persistence and EventuateAkka Persistence and Eventuate
Akka Persistence and Eventuate
 
Microservices in Scala: Play Framework
Microservices in Scala: Play FrameworkMicroservices in Scala: Play Framework
Microservices in Scala: Play Framework
 
Deep Introduction to Akka
Deep Introduction to AkkaDeep Introduction to Akka
Deep Introduction to Akka
 
Scala + Akka + ning/async-http-client - Vancouver Scala meetup February 2015
Scala + Akka + ning/async-http-client - Vancouver Scala meetup February 2015Scala + Akka + ning/async-http-client - Vancouver Scala meetup February 2015
Scala + Akka + ning/async-http-client - Vancouver Scala meetup February 2015
 
scalaphx-akka-http
scalaphx-akka-httpscalaphx-akka-http
scalaphx-akka-http
 
Codemotion akka persistence, cqrs%2 fes y otras siglas del montón
Codemotion   akka persistence, cqrs%2 fes y otras siglas del montónCodemotion   akka persistence, cqrs%2 fes y otras siglas del montón
Codemotion akka persistence, cqrs%2 fes y otras siglas del montón
 
Reactive programming with scala and akka
Reactive programming with scala and akkaReactive programming with scala and akka
Reactive programming with scala and akka
 
Akka Streams
Akka StreamsAkka Streams
Akka Streams
 
Event Sourcing using Akka on AWS
Event Sourcing using Akka on AWSEvent Sourcing using Akka on AWS
Event Sourcing using Akka on AWS
 
Akka-http
Akka-httpAkka-http
Akka-http
 
CQRS+ESをAkka Persistenceを使って実装してみる。
CQRS+ESをAkka Persistenceを使って実装してみる。CQRS+ESをAkka Persistenceを使って実装してみる。
CQRS+ESをAkka Persistenceを使って実装してみる。
 
JavaOne: A tour of (advanced) akka features in 60 minutes [con1706]
JavaOne: A tour of (advanced) akka features in 60 minutes [con1706]JavaOne: A tour of (advanced) akka features in 60 minutes [con1706]
JavaOne: A tour of (advanced) akka features in 60 minutes [con1706]
 
Akka Http , Routes, Streams with Scala
Akka Http , Routes, Streams with ScalaAkka Http , Routes, Streams with Scala
Akka Http , Routes, Streams with Scala
 
The Cloud-natives are RESTless @ JavaOne
The Cloud-natives are RESTless @ JavaOneThe Cloud-natives are RESTless @ JavaOne
The Cloud-natives are RESTless @ JavaOne
 
Akka http 2
Akka http 2Akka http 2
Akka http 2
 
Akka http
Akka httpAkka http
Akka http
 
spray: REST on Akka (Scala Days)
spray: REST on Akka (Scala Days)spray: REST on Akka (Scala Days)
spray: REST on Akka (Scala Days)
 
Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
 
Introduction to Actor Model and Akka
Introduction to Actor Model and AkkaIntroduction to Actor Model and Akka
Introduction to Actor Model and Akka
 
Practical Akka HTTP - introduction
Practical Akka HTTP - introductionPractical Akka HTTP - introduction
Practical Akka HTTP - introduction
 

Similar to Akka persistence webinar

How Not to Build a WordPress Plugin
How Not to Build a WordPress PluginHow Not to Build a WordPress Plugin
How Not to Build a WordPress Plugin
Will Norris
 
Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
IndicThreads
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
vhazrati
 

Similar to Akka persistence webinar (20)

Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)
 
BPM-3 Advanced Workflow Deep Dive
BPM-3 Advanced Workflow Deep DiveBPM-3 Advanced Workflow Deep Dive
BPM-3 Advanced Workflow Deep Dive
 
Async all around us (promises)
Async all around us (promises)Async all around us (promises)
Async all around us (promises)
 
Integrating Wicket with Java EE 6
Integrating Wicket with Java EE 6Integrating Wicket with Java EE 6
Integrating Wicket with Java EE 6
 
Data in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data EfficientlyData in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data Efficiently
 
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
 
Data in Motion: Streaming Static Data Efficiently 2
Data in Motion: Streaming Static Data Efficiently 2Data in Motion: Streaming Static Data Efficiently 2
Data in Motion: Streaming Static Data Efficiently 2
 
Advanced Akka For Architects
Advanced Akka For ArchitectsAdvanced Akka For Architects
Advanced Akka For Architects
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
 
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
 
Using Akka Persistence to build a configuration datastore
Using Akka Persistence to build a configuration datastoreUsing Akka Persistence to build a configuration datastore
Using Akka Persistence to build a configuration datastore
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014
 
How Not to Build a WordPress Plugin
How Not to Build a WordPress PluginHow Not to Build a WordPress Plugin
How Not to Build a WordPress Plugin
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30)
 
Higher Order Components and Render Props
Higher Order Components and Render PropsHigher Order Components and Render Props
Higher Order Components and Render Props
 
Overview Of Lift Framework
Overview Of Lift FrameworkOverview Of Lift Framework
Overview Of Lift Framework
 
Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
 

Recently uploaded

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Recently uploaded (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 

Akka persistence webinar

  • 1. Akka Persistence Webinar by Patrik Nordwall
 @patriknw
  • 2. opt-in at-least-once delivery semantics between actors recover application state after a crash
  • 3. Akka 2.3.0 Release 
 "com.typesafe.akka" %% "akka-persistence-experimental" % "2.3.0"
 <dependency> <groupId>com.typesafe.akka</groupId> <artifactId>akka-persistence-experimental_2.10</artifactId> <version>2.3.0</version> </dependency>
  • 4. Martin Krasser
 Twitter: mrt1nz
 Github: krasserm Eventsourced
 
 akka-persistence
 September 2013 - February 2014 
 contractor for Typesafe Awesome work, Martin!
  • 6. storing state transitions Cart Created Added 2 Socks Added 2 Shirts Shipping Info Added
  • 7. Akka  Persistence  Webinar Domain Events • things that have completed, facts • immutable • verbs in past tense • CustomerRelocated • CargoShipped • InvoiceSent “State transitions are an important part of our problem space and should be modeled within our domain.”   Greg Young, 2008
  • 8. Akka  Persistence  Webinar Benefits • Bullet-proof auditing and historical tracing • Support future ways of looking at data • Performance and scalability • Testability • Reconstruct production scenarios • No object-relational impedance mismatch • Nice fit with actors
  • 9. Akka  Persistence  Webinar Command Sourcing Event Sourcing write-ahead-log derive events from a command same behavior during recovery as normal operation external interaction can be problematic only state-changing behavior during recovery persisted before validation events cannot fail allows retroactive changes to the business logic fixing the business logic will not affect persisted events naming: represent intent, imperative naming: things that have completed, verbs in past tense
  • 10. Akka  Persistence  Webinar Consistency boundary • An actor is a consistency boundary • DDD Aggregate • No distributed transactions • eventually consistent • compensating actions
  • 11. Akka  Persistence  Webinar Life beyond Distributed Transactions: an Apostate’s Opinion Position Paper Pat Helland “In general, application developers simply do not implement large scalable applications assuming distributed transactions.”   Pat Helland http://www-­‐db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf
  • 13. Processor import akka.persistence.{ Persistent, Processor } ! class MyProcessor extends Processor { def receive = { case Persistent(payload, sequenceNr) => // message successfully written to journal case other => // message not written to journal } } val processor = context.actorOf(Props[MyProcessor],
 name = "myProcessor") ! processor ! Persistent("foo") // will be journaled processor ! "bar" // will not be journaled
  • 14. Processor class InvoiceService extends Processor { var invoices = Map.empty[String, Invoice] ! def receive: Receive = { case Persistent(CreateInvoice(id), _) => invoices = invoices.updated(id, Invoice(id)) } }
  • 15. Processor class InvoiceService extends Processor { var invoices = Map.empty[String, Invoice] ! def receive: Receive = { case Persistent(CreateInvoice(id), _) => invoices = invoices.updated(id, Invoice(id)) ! case Persistent(AddInvoiceItem(id, item), _) => invoices.get(id) match { case Some(inv) => invoices = invoices.updated(id, inv.addItem(item)) case None => // TODO } ! case GetInvoice(id) => sender() ! invoices.getOrElse(id, "not found: " + id) ! case Persistent(SendInvoiceTo(id, address), _) => // TODO send to the invoice printing service } }
  • 16. Processor case class CreateInvoice(invoiceId: String) case class AddInvoiceItem(invoiceId: String, invoiceItem: InvoiceItem) case class SendInvoiceTo(invoiceId: String, to: InvoiceAddress) case class GetInvoice(invoiceId: String) ! case class Invoice(id: String, items: IndexedSeq[InvoiceItem] = Vector.empty) { def addItem(item: InvoiceItem): Invoice = copy(items = items :+ item) } ! case class InvoiceItem(description: String, count: Int, amount: BigDecimal) ! case class InvoiceAddress(name: String, street: String, city: String)
  • 17. Processor Identifier 
 override def processorId = "my-stable-processor-id" Default is actor path without address
 /user/top/myProcessor Don’t use anonymous processors
  • 18. Akka  Persistence  Webinar Processor • Automatic recovery on start and restart • Stashing until recovery completed • Failure handling with supervisor strategy • Might want to delete erroneous messages
  • 19. What about side effects during replay?
  • 20. Processor with Channel val printingChannel = context.actorOf(Channel.props(), name = "printingChannel") val printingDestination = context.system / "printingService" ! def receive: Receive = { case p @ Persistent(SendInvoiceTo(id, address), _) => // send to the invoice printing service invoices.get(id) match { case Some(inv) => printingChannel ! Deliver(p.withPayload( PrintingOrder(inv, address)), printingDestination) invoices -= inv.id case None => // TODO } } class PrintingService extends Actor { def receive = { case p @ ConfirmablePersistent(payload, sequenceNr, redeliveries) => // ... p.confirm() } }
  • 21. Akka  Persistence  Webinar EventsourcedProcessor • Incoming messages (commands) are not persisted • Steps: 1. Validate command 2. Create domain event and explicitly persist it 3. Update internal state, by applying the event 4. External side effects • During recovery the internal state is updated by applying the events • no external side effects
  • 22. EventsourcedProcessor class BlogPost extends EventsourcedProcessor { override def receiveCommand: Receive = ???
 override def receiveRecover: Receive = ??? }
  • 23. EventsourcedProcessor object BlogPost { case class AddPost(author: String, title: String) } ! class BlogPost extends EventsourcedProcessor { override def receiveCommand: Receive = ???
 override def receiveRecover: Receive = ??? }
  • 24. object BlogPost { case class AddPost(author: String, title: String) } ! class BlogPost extends EventsourcedProcessor { import BlogPost._ ! override def receiveCommand: Receive = { case AddPost(author, title) => persist(PostAdded(author, title)) { evt => state = state.updated(evt) } } ! override def receiveRecover: Receive = ??? } EventsourcedProcessor
  • 25. EventsourcedProcessor object BlogPost { case class AddPost(author: String, title: String) ! sealed trait Event case class PostAdded(author: String, title: String) extends Event ! private case class State(author: String, title: String) { def updated(evt: Event): State = evt match { case PostAdded(author, title) => copy(author, title) } } } ! class BlogPost extends EventsourcedProcessor { import BlogPost._ private var state = State("", “") ! override def receiveCommand: Receive = { case AddPost(author, title) => persist(PostAdded(author, title)) { evt => state = state.updated(evt) } } ! override def receiveRecover: Receive = ??? }
  • 26. EventsourcedProcessor object BlogPost { case class AddPost(author: String, title: String) case class ChangeBody(body: String) case object Publish ! sealed trait Event case class PostAdded(author: String, title: String) extends Event case class BodyChanged(body: String) extends Event case object PostPublished extends Event ! private case class State(author: String, title: String, body: String, published: Boolean) { ! def updated(evt: Event): State = evt match { case PostAdded(author, title) => copy(author, title) case BodyChanged(b) => copy(body = b) case PostPublished => copy(published = true) } } }
  • 27. EventsourcedProcessor class BlogPost extends EventsourcedProcessor { import BlogPost._ private var state = State("", "", "", false) ! override def receiveCommand: Receive = { case AddPost(author, title) => if (state.body == "" && author != "" && title != "") persist(PostAdded(author, title)) { evt => state = state.updated(evt) } case ChangeBody(body) => if (!state.published) persist(BodyChanged(body)) { evt => state = state.updated(evt) } case Publish => if (!state.published) persist(PostPublished) { evt => state = state.updated(evt) // call external web content service ... } } ! override def receiveRecover: Receive = { case evt: Event => state = state.updated(evt) } }
  • 28. Snapshots class MyProcessor extends Processor { var state: Any = _ def receive = { case "snap" => saveSnapshot(state) case SaveSnapshotSuccess(metadata) => // ... case SaveSnapshotFailure(metadata, reason) => // ... } }
  • 29. Snapshots class MyProcessor extends Processor { var state: Any = _ def receive = { case "snap" => saveSnapshot(state) case SaveSnapshotSuccess(metadata) => // ... case SaveSnapshotFailure(metadata, reason) => // ... ! case SnapshotOffer(metadata, offeredSnapshot) => state = offeredSnapshot case Persistent(payload, _) => // ... } }
  • 30. Akka  Persistence  Webinar View • replays Persistent messages from a Processor’s journal • query side of CQRS • features • auto-update interval • Update message • limit • may store its own snapshots
  • 31. View class InvoiceCounter extends View { import InvoiceCounter._ override def processorId: String = "/user/invoiceService" override def autoUpdateInterval = 10.seconds ! var count = 0L ! def receive: Actor.Receive = { case Persistent(payload: SendInvoiceTo, _) => count += 1 case _: Persistent => case GetInvoiceCount => sender ! InvoiceCount(count) } } ! object InvoiceCounter { case object GetInvoiceCount case class InvoiceCount(count: Long) }
  • 33. Akka  Persistence  Webinar At-least-once delivery sender destination $
  • 34. Akka  Persistence  Webinar At-least-once delivery sender destination $ ok $ ok
  • 35. Akka  Persistence  Webinar Channels • re-deliver messages until confirmed • application level confirmation • different semantics • duplicates may be received • message order not retained • after a crash and restart messages are still delivered • listener for RedeliverFailure notifications • recommendation: one destination per channel 
 exception: replies via channel
  • 36. Akka  Persistence  Webinar Channel vs. PersistentChannel • Channel • use from Processor • in-memory • PersistentChannel • standalone usage • conceptually: processor + channel • persist messages before delivering • reply ack when persisted • more advanced delivery flow control
  • 37. Processor with Channel class MyProcessor extends Processor { val channel = context.actorOf(Channel.props(), name = "myChannel") ! def receive = { case p @ Persistent(payload, _) => val destination = context.system / "myDestination" channel ! Deliver(p.withPayload("output msg"), destination) } } ! class MyDestination extends Actor { def receive = { case p @ ConfirmablePersistent(payload, sequenceNr, redeliveries) => // ... p.confirm() } }
  • 38. PersistentChannel class Endpoint extends Actor { val channel = context.actorOf(PersistentChannel.props( PersistentChannelSettings(redeliverInterval = 3.seconds, redeliverMax = 10, replyPersistent = true)), name = "myChannel") val destination = context.system / "jobManager" ! import context.dispatcher implicit val timeout = Timeout(5.seconds) ! def receive = { case job: Job => (channel ? Deliver(Persistent(job), destination)) map { case _: Persistent => "OK: " + job.id } recover { case e => "FAILED: " + job.id } pipeTo sender() } }
  • 39. Akka  Persistence  Webinar Serialization • pluggable, Akka serialization • application life-cycle, versioning • don’t use default Java serialization
  • 40. Akka  Persistence  Webinar Journal and snapshot store • pluggable • LevelDB shipped with Akka – local files • Community http://akka.io/community/ • BDB • Cassandra • DynamoDB • HBase • MapDB • MongoDB
  • 41. Akka  Persistence  Webinar Cluster • simple way of migrating/moving stateful actors in a cluster • distributed journal • shared LevelDB journal for testing • single writer per event stream • cluster singleton • cluster sharding
  • 43. Akka  Persistence  Webinar Cluster Singleton A B C D role: backend-1 role: backend-1 role: backend-2 role: backend-2
  • 45. Akka  Persistence  Webinar Cluster Sharding sender id:17 region
 node-­‐1 coordinator region
 node-­‐2 region
 node-­‐3 GetShardHome:17 id:17 ShardHome:17  -­‐>  node2 17  -­‐>  node2
  • 46. Akka  Persistence  Webinar Cluster Sharding sender region
 node-­‐1 coordinator region
 node-­‐2 region
 node-­‐3 id:17 id:17 GetShardHome:17 ShardHome:17  -­‐>  node2 id:17 17  -­‐>  node2 17  -­‐>  node2
  • 47. Akka  Persistence  Webinar Cluster Sharding 17 sender region
 node-­‐1 coordinator region
 node-­‐2 region
 node-­‐3 id:17 id:17 17  -­‐>  node2 17  -­‐>  node2 17  -­‐>  node2
  • 48. Akka  Persistence  Webinar Cluster Sharding 17 sender region
 node-­‐1 coordinator region
 node-­‐2 region
 node-­‐3 17  -­‐>  node2 17  -­‐>  node2 17  -­‐>  node2 id:17
  • 49. Akka  Persistence  Webinar Cluster Sharding 17 sender region
 node-­‐1 coordinator region
 node-­‐2 region
 node-­‐3 17  -­‐>  node2 17  -­‐>  node2 17  -­‐>  node2 id:17
  • 50. Cluster Sharding val idExtractor: ShardRegion.IdExtractor = { case cmd: Command => (cmd.postId, cmd) } ! val shardResolver: ShardRegion.ShardResolver = msg => msg match { case cmd: Command => (math.abs(cmd.postId.hashCode) % 100).toString } ClusterSharding(system).start( typeName = BlogPost.shardName, entryProps = Some(BlogPost.props()), idExtractor = BlogPost.idExtractor, shardResolver = BlogPost.shardResolver) val postRegion: ActorRef = 
 ClusterSharding(context.system).shardRegion(BlogPost.shardName) ! val postId = UUID.randomUUID().toString postRegion ! BlogPost.AddPost(postId, author, title)
  • 52. Akka  Persistence  Webinar Next step • Documentation • http://doc.akka.io/docs/akka/2.3.0/scala/persistence.html • http://doc.akka.io/docs/akka/2.3.0/java/persistence.html • http://doc.akka.io/docs/akka/2.3.0/contrib/cluster-sharding.html • Typesafe Activator • https://typesafe.com/activator/template/akka-sample-persistence-scala • https://typesafe.com/activator/template/akka-sample-persistence-java • http://typesafe.com/activator/template/akka-cluster-sharding-scala • Mailing list • http://groups.google.com/group/akka-user • Migration guide from Eventsourced • http://doc.akka.io/docs/akka/2.3.0/project/migration-guide-eventsourced-2.3.x.html
  • 53. Akka  Persistence  Webinar Akka in Action • All registrants for this webinar qualify for a free E-Book PDF subset of Akka in Action by Raymond Roestenburg, Rob Bakker and Rob Williams. Additionally, you will qualify for the Typesafe discount and can save 40% on the full book.
  • 54. ©Typesafe 2014 – All Rights Reserved