SlideShare ist ein Scribd-Unternehmen logo
1 von 33
Downloaden Sie, um offline zu lesen
Aecor
Purely functional event sourcing
Denis Mikhaylov
@notxcain
Aecor ⇒ Purely functional event sourcing by @notxcain 1
Vanilla
id owner balance
1 John 50
do debitAccount(accountId: AccountId, amount: Amount) = for {
state <- loadState(accountId)
(nextState, result) <- state.debit(amount)
_ <- saveState(accountId, nextState)
} yield result
Aecor ⇒ Purely functional event sourcing by @notxcain 2
Event sourcing
id seqNr event
Account-1 1 Opened(John)
Account-1 2 Credited(100)
Account-1 3 Debited(50)
Aecor ⇒ Purely functional event sourcing by @notxcain 3
Event sourcing
do debitAccount(accountId: AccountId, amount: Amount) = for {
events <- loadEvents(accountId)
state = events.foldLeft(zeroState)(_ applyEvent _)
(newEvents, result) <- state.debit(amount)
_ <- appendEvents(accountId, newEvents)
} yield result
Aecor ⇒ Purely functional event sourcing by @notxcain 4
Event
• What?
• When?
• Who?
• Where?
Aecor ⇒ Purely functional event sourcing by @notxcain 5
Isn’t that great?
• Change log
• Complex temporal, retroactive queries
• Time-travel debugging
• Scalable, HA stores (Cassandra, Couchbase, etc.)
• Event based service integration (reactive bla bla)
Aecor ⇒ Purely functional event sourcing by @notxcain 6
Toolkit?
Aecor ⇒ Purely functional event sourcing by @notxcain 7
Toolkit?
• Purely functional behaviors
• Purely functional runtime
• Scalable
• Composable
• Testable
Aecor ⇒ Purely functional event sourcing by @notxcain 8
Aecorhttps://aecor.io
Aecor ⇒ Purely functional event sourcing by @notxcain 9
Aecor
• modular framework library
• composable primitives
• runtimes
Aecor ⇒ Purely functional event sourcing by @notxcain 10
Akka Persistence Runtime
• akka-cluster-sharding
• akka-persistence
• akka-persistence-cassandra
• cats
• typesafe encoding/decoding
Aecor ⇒ Purely functional event sourcing by @notxcain 11
Behavior
final case class EventsourcedBehavior[F[_], Op[_], State, Event](
handler: Op ~> Handler[F, State, Event, ?],
zero: State,
reducer: (State, Event) => Folded[State]
)
Aecor ⇒ Purely functional event sourcing by @notxcain 12
State
zero: S
reducer: (S, E) => Folded[E]
sealed abstract class Folded[+A] extends Product with Serializable
final case object Impossible extends Folded[Nothing]
final case class Next[+A](a: A) extends Folded[A]
Aecor ⇒ Purely functional event sourcing by @notxcain 13
Operations
trait RepliesWith[A]
Aecor ⇒ Purely functional event sourcing by @notxcain 14
Operations
trait RepliesWith[A]
sealed abstract class AccountOp[A] extends Product with Serializable {
def accountId: AccountId
}
final case class OpenAccount(accountId: AccountId)
extends AccountOp[Either[OpenAccountRejection, Unit]]
final case class CreditAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount)
extends AccountOp[Either[CreditAccountRejection, Unit]]
final case class DebitAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount)
extends AccountOp[Either[DebitAccountRejection, Unit]]
Aecor ⇒ Purely functional event sourcing by @notxcain 15
Operation handler
type Handler[F[_], S, E, A] =
S => F[(Seq[E], A)]
Aecor ⇒ Purely functional event sourcing by @notxcain 16
Operation handler
type Handler[F[_], S, E, A] =
S => F[(Seq[E], A)]
type VanillaHandler[F[_], S, A] =
S => F[(S, A)]
Aecor ⇒ Purely functional event sourcing by @notxcain 17
Operation handler
type Handler[F[_], S, E, A] =
S => F[(Seq[E], A)]
type OperationHandler[F[_], Op[_], S, E] =
Op ~> Handler[F, S, E, ?]
Aecor ⇒ Purely functional event sourcing by @notxcain 18
Behavior
final case class EventsourcedBehavior[F[_], Op[_], State, Event](
handler: Op ~> Handler[F, State, Event, ?],
zero: State,
reducer: (State, Event) => Folded[State]
)
Aecor ⇒ Purely functional event sourcing by @notxcain 19
Show Time
class AkkaPersistenceRuntime[F[_]: Async: CaptureFuture: Capture: Monad](system: ActorSystem) {
def start[Op[_], State, Event: PersistentEncoder: PersistentDecoder](
entityName: String,
correlation: Correlation[Op], // Op[_] => String
behavior: EventsourcedBehavior[F, Op, State, Event],
tagging: Tagging[Event], // Event => EventTag[Event]
snapshotPolicy: SnapshotPolicy[State],
settings: AkkaPersistenceRuntimeSettings
): F[Op ~> F] = ...
}
Aecor ⇒ Purely functional event sourcing by @notxcain 20
Event tagging
AccountOpened(1, John) -> Account0
AccountOpened(2, Mike) -> Account1
AccountOpened(3, Bill) -> Account0
Aecor ⇒ Purely functional event sourcing by @notxcain 21
Reading events
trait EventJournalQuery[Offset, E] {
def eventsByTag(
tag: EventTag[E],
offset: Option[Offset]
): Source[JournalEntry[Offset, E], NotUsed]
}
Aecor ⇒ Purely functional event sourcing by @notxcain 22
Reading events
trait EventJournalQuery[Offset, E] {
def committableEventsByTag[F[_]: Async](
offsetStore: OffsetStore[F, Offset],
tag: EventTag[E],
consumerId: ConsumerId
): Source[Committable[F, JournalEntry[Offset, E]], NotUsed]
}
final case class Committable[F[_], +A](commit: F[Unit], value: A)
Aecor ⇒ Purely functional event sourcing by @notxcain 23
Process
1. React to changes (events, time)
2. Perform actions
3. ???
4. PROFIT Eventual Consistency
Aecor ⇒ Purely functional event sourcing by @notxcain 24
Co-things?
Entity : Actions -> Changes
Process : Changes -> Actions
Aecor ⇒ Purely functional event sourcing by @notxcain 25
Process
Top 2
• Views
• Business-processes
Aecor ⇒ Purely functional event sourcing by @notxcain 26
Distributed Processing
final case class Process[F[_]](run: F[RunningProcess[F]])
Aecor ⇒ Purely functional event sourcing by @notxcain 27
Distributed Processing
final case class Process[F[_]](run: F[RunningProcess[F]])
final case class RunningProcess[F[_]](
watchTermination: F[Unit],
shutdown: () => Unit
)
Aecor ⇒ Purely functional event sourcing by @notxcain 28
Distributed Processing
def start[F[_]: Async: Capture: CaptureFuture: Functor](
name: String,
processes: Seq[Process[F]],
settings: DistributedProcessingSettings
): F[ProcessKillSwitch[F]] = ...
final case class ProcessKillSwitch[F[_]](shutdown: F[Unit])
Aecor ⇒ Purely functional event sourcing by @notxcain 29
Aecor - what else?
Experimental runtime for generic behaviors
final case class Behavior[F[_], Op[_]](run: Op ~> PairT[F, Behavior[F, Op], ?])
class GenericAkkaRuntime[F[_]: Async: CaptureFuture: Functor: Capture](system: ActorSystem) {
def start[Op[_]](entityName: String,
correlation: Correlation[Op],
behavior: Behavior[F, Op],
settings: GenericAkkaRuntimeSettings
): F[Op ~> F]
}
Aecor ⇒ Purely functional event sourcing by @notxcain 30
Aecor - what else?
Liberator (free algebra for trait, and many more)
@algebra
trait Account[F[_]] {
def openAccount(accountId: AccountId, owner: AccountOwner): F[Either[OpenAccountRejection, Unit]]
}
class EventSourcedAccount[F[_]](clock: F[ZonedDateTime])
extends Account[Handler[F, AccountState, AccountEvent, ?]]
val account: EventSourcedAggregate[Task] = ...
val handler: AccountOp ~> Handler[F, AccountState, AccountEvent, ?] = account.asFunctionK
Aecor ⇒ Purely functional event sourcing by @notxcain 31
Adopters
• Evotor (https://evotor.ru)
• Your name here
Aecor ⇒ Purely functional event sourcing by @notxcain 32
Q&Ahttps://aecor.io
Aecor ⇒ Purely functional event sourcing by @notxcain 33

Weitere ähnliche Inhalte

Ähnlich wie Aecor. Purely functional event sourcing

Mobx Performance and Sanity
Mobx Performance and SanityMobx Performance and Sanity
Mobx Performance and Sanity500Tech
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionJenya Terpil
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionFDConf
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)guiwoda
 
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
 
POC d'une architecture distribuee de calculs financiers
POC d'une architecture distribuee de calculs financiersPOC d'une architecture distribuee de calculs financiers
POC d'une architecture distribuee de calculs financiersxbucchiotty
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creatorsGeorge Bukhanov
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...Databricks
 
Taming Distribution: Formal Protocols for Akka Typed
Taming Distribution: Formal Protocols for Akka TypedTaming Distribution: Formal Protocols for Akka Typed
Taming Distribution: Formal Protocols for Akka TypedRoland Kuhn
 
aming distribution: formal protocols for Akka Typed
aming distribution: formal protocols for Akka Typedaming distribution: formal protocols for Akka Typed
aming distribution: formal protocols for Akka TypedJ On The Beach
 
Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Paco de la Cruz
 
Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsICSM 2010
 
Droid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroidConTLV
 
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Chris Richardson
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Distributed Stream Processing with WSO2 Stream Processor
Distributed Stream Processing with WSO2 Stream ProcessorDistributed Stream Processing with WSO2 Stream Processor
Distributed Stream Processing with WSO2 Stream ProcessorWSO2
 
Bridging the Gap between Requirements Modeling and Behavior-driven Development
Bridging the Gap between Requirements Modeling and Behavior-driven DevelopmentBridging the Gap between Requirements Modeling and Behavior-driven Development
Bridging the Gap between Requirements Modeling and Behavior-driven DevelopmentLionel Briand
 

Ähnlich wie Aecor. Purely functional event sourcing (20)

Mobx Performance and Sanity
Mobx Performance and SanityMobx Performance and Sanity
Mobx Performance and Sanity
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
react.pdf
react.pdfreact.pdf
react.pdf
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
 
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...
 
POC d'une architecture distribuee de calculs financiers
POC d'une architecture distribuee de calculs financiersPOC d'une architecture distribuee de calculs financiers
POC d'une architecture distribuee de calculs financiers
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
 
Taming Distribution: Formal Protocols for Akka Typed
Taming Distribution: Formal Protocols for Akka TypedTaming Distribution: Formal Protocols for Akka Typed
Taming Distribution: Formal Protocols for Akka Typed
 
aming distribution: formal protocols for Akka Typed
aming distribution: formal protocols for Akka Typedaming distribution: formal protocols for Akka Typed
aming distribution: formal protocols for Akka Typed
 
Clojure functions examples
Clojure functions examplesClojure functions examples
Clojure functions examples
 
Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)
 
Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method Declarations
 
Droid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, Kik
 
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
 
Solving the n + 1 query problem
Solving the n + 1 query problemSolving the n + 1 query problem
Solving the n + 1 query problem
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Distributed Stream Processing with WSO2 Stream Processor
Distributed Stream Processing with WSO2 Stream ProcessorDistributed Stream Processing with WSO2 Stream Processor
Distributed Stream Processing with WSO2 Stream Processor
 
Bridging the Gap between Requirements Modeling and Behavior-driven Development
Bridging the Gap between Requirements Modeling and Behavior-driven DevelopmentBridging the Gap between Requirements Modeling and Behavior-driven Development
Bridging the Gap between Requirements Modeling and Behavior-driven Development
 

Kürzlich hochgeladen

Sales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageSales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageDista
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeNeo4j
 
Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampVICTOR MAESTRE RAMIREZ
 
Watermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesWatermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesShyamsundar Das
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxJoão Esperancinha
 
Top Software Development Trends in 2024
Top Software Development Trends in  2024Top Software Development Trends in  2024
Top Software Development Trends in 2024Mind IT Systems
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsJaydeep Chhasatia
 
JS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIJS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIIvo Andreev
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorShane Coughlan
 
AI Embracing Every Shade of Human Beauty
AI Embracing Every Shade of Human BeautyAI Embracing Every Shade of Human Beauty
AI Embracing Every Shade of Human BeautyRaymond Okyere-Forson
 
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...OnePlan Solutions
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfBrain Inventory
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptkinjal48
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.Sharon Liu
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?AmeliaSmith90
 
Growing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesGrowing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesSoftwareMill
 
online pdf editor software solutions.pdf
online pdf editor software solutions.pdfonline pdf editor software solutions.pdf
online pdf editor software solutions.pdfMeon Technology
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntelliSource Technologies
 
Generative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilGenerative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilVICTOR MAESTRE RAMIREZ
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionsNirav Modi
 

Kürzlich hochgeladen (20)

Sales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageSales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales Coverage
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG time
 
Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - Datacamp
 
Watermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesWatermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security Challenges
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptx
 
Top Software Development Trends in 2024
Top Software Development Trends in  2024Top Software Development Trends in  2024
Top Software Development Trends in 2024
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
 
JS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIJS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AI
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS Calculator
 
AI Embracing Every Shade of Human Beauty
AI Embracing Every Shade of Human BeautyAI Embracing Every Shade of Human Beauty
AI Embracing Every Shade of Human Beauty
 
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdf
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.ppt
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?
 
Growing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesGrowing Oxen: channel operators and retries
Growing Oxen: channel operators and retries
 
online pdf editor software solutions.pdf
online pdf editor software solutions.pdfonline pdf editor software solutions.pdf
online pdf editor software solutions.pdf
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptx
 
Generative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilGenerative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-Council
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspections
 

Aecor. Purely functional event sourcing

  • 1. Aecor Purely functional event sourcing Denis Mikhaylov @notxcain Aecor ⇒ Purely functional event sourcing by @notxcain 1
  • 2. Vanilla id owner balance 1 John 50 do debitAccount(accountId: AccountId, amount: Amount) = for { state <- loadState(accountId) (nextState, result) <- state.debit(amount) _ <- saveState(accountId, nextState) } yield result Aecor ⇒ Purely functional event sourcing by @notxcain 2
  • 3. Event sourcing id seqNr event Account-1 1 Opened(John) Account-1 2 Credited(100) Account-1 3 Debited(50) Aecor ⇒ Purely functional event sourcing by @notxcain 3
  • 4. Event sourcing do debitAccount(accountId: AccountId, amount: Amount) = for { events <- loadEvents(accountId) state = events.foldLeft(zeroState)(_ applyEvent _) (newEvents, result) <- state.debit(amount) _ <- appendEvents(accountId, newEvents) } yield result Aecor ⇒ Purely functional event sourcing by @notxcain 4
  • 5. Event • What? • When? • Who? • Where? Aecor ⇒ Purely functional event sourcing by @notxcain 5
  • 6. Isn’t that great? • Change log • Complex temporal, retroactive queries • Time-travel debugging • Scalable, HA stores (Cassandra, Couchbase, etc.) • Event based service integration (reactive bla bla) Aecor ⇒ Purely functional event sourcing by @notxcain 6
  • 7. Toolkit? Aecor ⇒ Purely functional event sourcing by @notxcain 7
  • 8. Toolkit? • Purely functional behaviors • Purely functional runtime • Scalable • Composable • Testable Aecor ⇒ Purely functional event sourcing by @notxcain 8
  • 9. Aecorhttps://aecor.io Aecor ⇒ Purely functional event sourcing by @notxcain 9
  • 10. Aecor • modular framework library • composable primitives • runtimes Aecor ⇒ Purely functional event sourcing by @notxcain 10
  • 11. Akka Persistence Runtime • akka-cluster-sharding • akka-persistence • akka-persistence-cassandra • cats • typesafe encoding/decoding Aecor ⇒ Purely functional event sourcing by @notxcain 11
  • 12. Behavior final case class EventsourcedBehavior[F[_], Op[_], State, Event]( handler: Op ~> Handler[F, State, Event, ?], zero: State, reducer: (State, Event) => Folded[State] ) Aecor ⇒ Purely functional event sourcing by @notxcain 12
  • 13. State zero: S reducer: (S, E) => Folded[E] sealed abstract class Folded[+A] extends Product with Serializable final case object Impossible extends Folded[Nothing] final case class Next[+A](a: A) extends Folded[A] Aecor ⇒ Purely functional event sourcing by @notxcain 13
  • 14. Operations trait RepliesWith[A] Aecor ⇒ Purely functional event sourcing by @notxcain 14
  • 15. Operations trait RepliesWith[A] sealed abstract class AccountOp[A] extends Product with Serializable { def accountId: AccountId } final case class OpenAccount(accountId: AccountId) extends AccountOp[Either[OpenAccountRejection, Unit]] final case class CreditAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount) extends AccountOp[Either[CreditAccountRejection, Unit]] final case class DebitAccount(accountId: AccountId, transactionId: AccountTransactionId, amount: Amount) extends AccountOp[Either[DebitAccountRejection, Unit]] Aecor ⇒ Purely functional event sourcing by @notxcain 15
  • 16. Operation handler type Handler[F[_], S, E, A] = S => F[(Seq[E], A)] Aecor ⇒ Purely functional event sourcing by @notxcain 16
  • 17. Operation handler type Handler[F[_], S, E, A] = S => F[(Seq[E], A)] type VanillaHandler[F[_], S, A] = S => F[(S, A)] Aecor ⇒ Purely functional event sourcing by @notxcain 17
  • 18. Operation handler type Handler[F[_], S, E, A] = S => F[(Seq[E], A)] type OperationHandler[F[_], Op[_], S, E] = Op ~> Handler[F, S, E, ?] Aecor ⇒ Purely functional event sourcing by @notxcain 18
  • 19. Behavior final case class EventsourcedBehavior[F[_], Op[_], State, Event]( handler: Op ~> Handler[F, State, Event, ?], zero: State, reducer: (State, Event) => Folded[State] ) Aecor ⇒ Purely functional event sourcing by @notxcain 19
  • 20. Show Time class AkkaPersistenceRuntime[F[_]: Async: CaptureFuture: Capture: Monad](system: ActorSystem) { def start[Op[_], State, Event: PersistentEncoder: PersistentDecoder]( entityName: String, correlation: Correlation[Op], // Op[_] => String behavior: EventsourcedBehavior[F, Op, State, Event], tagging: Tagging[Event], // Event => EventTag[Event] snapshotPolicy: SnapshotPolicy[State], settings: AkkaPersistenceRuntimeSettings ): F[Op ~> F] = ... } Aecor ⇒ Purely functional event sourcing by @notxcain 20
  • 21. Event tagging AccountOpened(1, John) -> Account0 AccountOpened(2, Mike) -> Account1 AccountOpened(3, Bill) -> Account0 Aecor ⇒ Purely functional event sourcing by @notxcain 21
  • 22. Reading events trait EventJournalQuery[Offset, E] { def eventsByTag( tag: EventTag[E], offset: Option[Offset] ): Source[JournalEntry[Offset, E], NotUsed] } Aecor ⇒ Purely functional event sourcing by @notxcain 22
  • 23. Reading events trait EventJournalQuery[Offset, E] { def committableEventsByTag[F[_]: Async]( offsetStore: OffsetStore[F, Offset], tag: EventTag[E], consumerId: ConsumerId ): Source[Committable[F, JournalEntry[Offset, E]], NotUsed] } final case class Committable[F[_], +A](commit: F[Unit], value: A) Aecor ⇒ Purely functional event sourcing by @notxcain 23
  • 24. Process 1. React to changes (events, time) 2. Perform actions 3. ??? 4. PROFIT Eventual Consistency Aecor ⇒ Purely functional event sourcing by @notxcain 24
  • 25. Co-things? Entity : Actions -> Changes Process : Changes -> Actions Aecor ⇒ Purely functional event sourcing by @notxcain 25
  • 26. Process Top 2 • Views • Business-processes Aecor ⇒ Purely functional event sourcing by @notxcain 26
  • 27. Distributed Processing final case class Process[F[_]](run: F[RunningProcess[F]]) Aecor ⇒ Purely functional event sourcing by @notxcain 27
  • 28. Distributed Processing final case class Process[F[_]](run: F[RunningProcess[F]]) final case class RunningProcess[F[_]]( watchTermination: F[Unit], shutdown: () => Unit ) Aecor ⇒ Purely functional event sourcing by @notxcain 28
  • 29. Distributed Processing def start[F[_]: Async: Capture: CaptureFuture: Functor]( name: String, processes: Seq[Process[F]], settings: DistributedProcessingSettings ): F[ProcessKillSwitch[F]] = ... final case class ProcessKillSwitch[F[_]](shutdown: F[Unit]) Aecor ⇒ Purely functional event sourcing by @notxcain 29
  • 30. Aecor - what else? Experimental runtime for generic behaviors final case class Behavior[F[_], Op[_]](run: Op ~> PairT[F, Behavior[F, Op], ?]) class GenericAkkaRuntime[F[_]: Async: CaptureFuture: Functor: Capture](system: ActorSystem) { def start[Op[_]](entityName: String, correlation: Correlation[Op], behavior: Behavior[F, Op], settings: GenericAkkaRuntimeSettings ): F[Op ~> F] } Aecor ⇒ Purely functional event sourcing by @notxcain 30
  • 31. Aecor - what else? Liberator (free algebra for trait, and many more) @algebra trait Account[F[_]] { def openAccount(accountId: AccountId, owner: AccountOwner): F[Either[OpenAccountRejection, Unit]] } class EventSourcedAccount[F[_]](clock: F[ZonedDateTime]) extends Account[Handler[F, AccountState, AccountEvent, ?]] val account: EventSourcedAggregate[Task] = ... val handler: AccountOp ~> Handler[F, AccountState, AccountEvent, ?] = account.asFunctionK Aecor ⇒ Purely functional event sourcing by @notxcain 31
  • 32. Adopters • Evotor (https://evotor.ru) • Your name here Aecor ⇒ Purely functional event sourcing by @notxcain 32
  • 33. Q&Ahttps://aecor.io Aecor ⇒ Purely functional event sourcing by @notxcain 33