SlideShare a Scribd company logo
Dennis Doomen | @ddoomen | Aviva Solutions | The Continuous Improver
Event Sourcing from the Trenches (DDD Europe 2020)
Event Sourcing from the Trenches (DDD Europe 2020)
Event Sourcing from the Trenches (DDD Europe 2020)
Event Sourcing from the Trenches (DDD Europe 2020)
Command Handlers
Commands
Domain Model
Event Store
Events
App
Query Store
Data Access
Projectors
Events
Query HTTP API
Projections
Events
Command HTTP API
Great unit
of testing
Great unit
of testing
Auditability
comes for free
Can look at
the state in
the past
Can be scaled
independently
Autonomous
projections
Aligns well
with Event
Storming
Forces you to
understand your
domain thoroughly
No relational
table structure
anymore.
Can replay old
data against new
rules
More difficult to
envisage domain
relationships
Great for
replication
Application
Command
Service
Correct
Customer
Email Handler
Customer
Unit of
Work
Projector
Data
Access
Layer
Read
Database Write
Database
CorrectCustomerEmailCommand
HTTP API / In-process invocation
Get<Customer>(identity)
Correct Email
Event Store
Load(events)
Apply
Get changes
CustomerEmailCorrectedEvent
Submit changes
History
Dennis Doomen | @ddoomen | The Continuous Improver
NES
Aggregates.NET
SimpleDomain
NStore
EventStore
NEventStore
SQLStreamStore
NStore
NES
Marten
Handelier
Brighter
MediatR (*)
Projac
LiquidProjections (*)
Dennis Doomen | @ddoomen | The Continuous Improver
Application
Domain
NoSQL / RDBMS
OR/M / DAL
Web UI, HTTP API,
etc
Lucene Index
Document Projector
Web UI, HTTP
API, etc
Web UI, HTTP API, etc
Domain
Commands
Events
Event StoreProjections
Projectors
Uses Event
Sourcing
Uses traditional
CRUD
architecture
Indexing-based
architecture
Subcribe
to
webhooks
Coarse-
grained
HTTP
requests.
Bus
Subscribe
Publish coarse-
grained event
Customer #123
Correct Customer
Shipping Address
Command
Customer Shipping
Address Corrected
Event
Event Store
Treat as a
message, not a
type
Order #456
Correct Shipping Address
Command Handler
Application
Customer Shipping Address
Corrected Handler
Order Redirected
Event.
Identity !=
natural key
Identify
partition key
Primitive types
only
Avoid terms like
Create, Update,
Delete, Change.
Avoid property
change events
Don’t use as
inter-domain
contracts
Don’t expose
outside the
domain
Dennis Doomen | @ddoomen | The Continuous Improver
Customer #123
Correct Customer
Shipping Address
Command
Customer Shipping
Address Corrected
Event
Event Store
Order #456
Correct Shipping Address
Command Handler
Application
Order Redirected
Event
Dennis Doomen | @ddoomen | The Continuous Improver
Command Service
Some Command
Handler
Customer #123
Event Store
Customer Created
Event
Get<Customer>(“123”)
Customer
Created Event
Converter
Customer Enrolled
Event
May split or
merge events
Can also run as
part of migration
May change the
identity
Unaffected Events
Dennis Doomen | @ddoomen | The Continuous Improver
Event
Store
Projector Projector
RDBMS
Subscribe
Subscribe
Document
DB
Projector
RDBMS
Subscribe
Raw SQLNHibernate RavenDB
Lookup
Autonomous &
independent
Storage technique
optimized for
projection
No joining of
projections
Avoid reusing the
projections for
multiple purposes
Use aggressive
caching during
rebuilds.
Caching strategy
optimized for
projector
Owned by
projector
Dennis Doomen | @ddoomen | The Continuous Improver
Stream-by-stream
projections during
rebuilds
var mapBuilder = new EventMapBuilder<MyContext, DocumentProjection, string>();
mapBuilder
.Map<WarrantAssignedEvent>()
.AsCreateOf(anEvent => anEvent.Number)
.Using((document, anEvent) =>
{
document.Type = "Warrant";
document.Kind = anEvent.Kind;
document.Country = anEvent.Country;
document.State = anEvent.InitialState;
});
mapBuilder
.Map<StateTransitionedEvent>()
.When(anEvent => anEvent.State != "Closed")
.AsUpdateOf(anEvent => anEvent.DocumentNumber)
.Using((document, anEvent) => document.State = anEvent.State);
Dennis Doomen | @ddoomen | The Continuous Improver
Transaction
Event Event
Transaction
Event Event
Transaction
Event Event
RDBMS
INSERT/UPDATE … WHERE …
Transaction
Event Event
Transaction
Event Event
Transaction
Event Event
RDBMS
INSERT/UPDATE … WHERE …
INSERT/UPDATE … WHERE …
INSERT/UPDATE … WHERE …
Unit of Work
Dennis Doomen | @ddoomen | The Continuous Improver
private async Task<ExceptionResolution> OnException(ProjectionException exception, int attempts)
{
if (IsTransient(exception))
{
if (attempts < 3)
{
await Task.Delay(TimeSpan.FromSeconds(attempts ^ 2));
return ExceptionResolution.Retry;
}
return ExceptionResolution.Abort;
}
else
{
if (exception.TransactionBatch.Count > 1)
{
return ExceptionResolution.RetryIndividual;
}
// Mark projection as corrupt
return ExceptionResolution.Ignore;
}
}
Dennis Doomen | @ddoomen | The Continuous Improver
Event Store
Projector
Subscription
Projection
Subscribes to events
from multiple
aggregates
Lookup
Event Store
Other Projector
Lookup Projector
Subscription
Subscription
Storage
(persistent)
Lookup
Event
Modifier
Modifies events
with lookup data
Receives
extended events
Dennis Doomen | @ddoomen | The Continuous Improver
var stats = new ProjectionStats(() => DateTime.UtcNow);
stats.StoreProperty("CountByDocument", "some setting key", "some value");
stats.LogEvent("CountByDocument", "some significant thing that happened");
stats.TrackProgress("CountByDocument", currentCheckpoint);
float? transactionsPerSecond = stats.GetSpeed("CountByDocument");
TimeSpan? eta = stats.GetTimeToReach("CountByDocument", targetCheckpoint);
public void Configure(IAppBuilder builder)
{
builder.UseStatistics(stats);
}
Dennis Doomen | @ddoomen | The Continuous Improver
IAppBuilder builder = ….
builder.UseStatistics(stats);
GET http://localhost/projectionStats/CountByDocument
{
"projectorId": "CountByDocument",
"lastCheckpoint": 1000,
"lastCheckpointUpdatedUtc": "2018-05-10T10:39:00Z",
"properties": [{
"key": "some setting key",
"value": "some value",
"lastUpdatedUtc": "2018-05-10T10:39:00Z"
}],
"eventsUrl": "http://localhost/projectionStats/CountByDocument/events"
}
Dennis Doomen | @ddoomen | The Continuous Improver
Document #1
Created Event
Event Store
Graph
Projector
Document #1
Closed Event
(other events)
Projector with
active
projections
Archiving
Projector
Start archiving
Document #1
Marked As
Archivable Event
Mark all events
as archivable
Tracks dependencies
between documents
Deletes
projections
related to
Document #1
Can skip all
archivable events
during next
rebuild.
Dennis Doomen | @ddoomen | The Continuous Improver
Event Store
Lucene
Projector
Document #1
Marked As
Archivable Event
Allows projectors
to clean up
Lucene Index
Take snapshot
Purge events
Tombstone
$tombstone
stream
Application
Document
Projector
Search.
Tracks deleted streams
for future references
Stream Tombstoned
Event
Search
Dennis Doomen | @ddoomen | The Continuous Improver
Event Store
Projector
Application
Version 2
Owns schema
(e.g. FluentMigrator)
Version 1
X
Involves down-time until
projections are rebuild
Dennis Doomen | @ddoomen | The Continuous Improver
Event Store
Projector
Application Application
Network Load Balancer
Event Store
Version 1 Version 2
events
Projection ProjectorProjection
bring off-line
Returns HTTP 503
(Service Unavailable)
Dennis Doomen | @ddoomen | The Continuous Improver
Returns HTTP 503
(Service Unavailable)
Event Sourcing from the Trenches (DDD Europe 2020)
Event Sourcing from the Trenches (DDD Europe 2020)
Dennis Doomen | @ddoomen | The Continuous Improver
Dennis Doomen
@ddoomen
Dennis Doomen | @ddoomen | The Continuous Improver
• The Good, The Bad and the Ugly of Event
Sourcing
https://www.continuousimprover.com/search/label/event%20sourcing
• Effective Aggregate Design (Vaughn Vernon)
http://dddcommunity.org/library/vernon_2011/
• Liquid Projections
https://www.liquidprojections.net
• Distributed Event Sourcing (Slides)
https://www.slideshare.net/dennisdoomen/building-occasionally-
connected-applications-using-event-sourcing
• Data schema changes in an event sourced
system (paper)
https://files.movereem.nl/2017saner-eventsourcing.pdf

More Related Content

PPTX
Slow Event Sourcing (re)projections - Just make them faster!
Dennis Doomen
 
PPT
Préparation des actions de maintenance corrective (www.livre-technique.com)
Livre Technique
 
PDF
Développement d’une application pour la gestion de stock.pdf
AbdelHadiTLM
 
PDF
Planification et_ordonnancement-2
mahdi hajji
 
PPT
03 les sinistres (2011)
lionelmachado
 
PDF
POO Java Chapitre 4 Heritage et Polymorphisme
Mouna Torjmen
 
PDF
Chapitre05 : Les tableaux
L’Université Hassan 1er Settat
 
PDF
Organiser son stand pour le forum des associations - Asso-web.com
Mathieu Prudent
 
Slow Event Sourcing (re)projections - Just make them faster!
Dennis Doomen
 
Préparation des actions de maintenance corrective (www.livre-technique.com)
Livre Technique
 
Développement d’une application pour la gestion de stock.pdf
AbdelHadiTLM
 
Planification et_ordonnancement-2
mahdi hajji
 
03 les sinistres (2011)
lionelmachado
 
POO Java Chapitre 4 Heritage et Polymorphisme
Mouna Torjmen
 
Chapitre05 : Les tableaux
L’Université Hassan 1er Settat
 
Organiser son stand pour le forum des associations - Asso-web.com
Mathieu Prudent
 

What's hot (20)

DOC
Front page format summer project
Nithin Varghese
 
PDF
Rapport projet c : Logiciel de gestion des ressources humaines
Hosni Mansour
 
PDF
Organisation maintenance
mohamoha1
 
PPTX
pp fokou
FOKOU MERVIO
 
PPTX
Les coûts de maintenance
Mouhcine Nahal
 
DOCX
Fiches mensuelles de suivi gestion yaou
oboubacar
 
PPTX
Technique de la valeur acquise
timeperformance
 
PDF
Seance 3- Programmation en langage C
Fahad Golra
 
PDF
gestion de projet et MS-project.pdf
anasoumous1
 
PDF
Cours python avancé
pierrepo
 
PDF
GETSION DES RESSOURCES HUMAINES ET PAIE MAROCAINE SOUS OPENERP V7.0
Abissa Khadija
 
PDF
CM Culture Entrepreneuriale partie2.pdf
FootballLovers9
 
PDF
Methode kanban
guestb3d8d997
 
PPTX
Présentation PPT CARSELFCARE
BILEL TLILI
 
PDF
Presentation formation en ligne 2014 (eLearning)
Simon Hénault
 
PDF
Les fondamentaux de langage C#
Youness Boukouchi
 
PPT
Qualite Ishikawa
Rémi Bachelet
 
PDF
Chapitre 02 : Variables, Expressions et Instructions
L’Université Hassan 1er Settat
 
PDF
Stage Informatique Jedida ZOUMAROU
Faïzath Jedida ZOUMAROU WALIS
 
PDF
Cours d'Algorithmique et langage C .pdf
kamalomari2
 
Front page format summer project
Nithin Varghese
 
Rapport projet c : Logiciel de gestion des ressources humaines
Hosni Mansour
 
Organisation maintenance
mohamoha1
 
pp fokou
FOKOU MERVIO
 
Les coûts de maintenance
Mouhcine Nahal
 
Fiches mensuelles de suivi gestion yaou
oboubacar
 
Technique de la valeur acquise
timeperformance
 
Seance 3- Programmation en langage C
Fahad Golra
 
gestion de projet et MS-project.pdf
anasoumous1
 
Cours python avancé
pierrepo
 
GETSION DES RESSOURCES HUMAINES ET PAIE MAROCAINE SOUS OPENERP V7.0
Abissa Khadija
 
CM Culture Entrepreneuriale partie2.pdf
FootballLovers9
 
Methode kanban
guestb3d8d997
 
Présentation PPT CARSELFCARE
BILEL TLILI
 
Presentation formation en ligne 2014 (eLearning)
Simon Hénault
 
Les fondamentaux de langage C#
Youness Boukouchi
 
Qualite Ishikawa
Rémi Bachelet
 
Chapitre 02 : Variables, Expressions et Instructions
L’Université Hassan 1er Settat
 
Stage Informatique Jedida ZOUMAROU
Faïzath Jedida ZOUMAROU WALIS
 
Cours d'Algorithmique et langage C .pdf
kamalomari2
 
Ad

Similar to Event Sourcing from the Trenches (DDD Europe 2020) (20)

PPTX
Event Sourcing from the Trenches (with examples from .NET)
Dennis Doomen
 
PPTX
The Good, The Bad and The Ugly of Event Sourcing
Dennis Doomen
 
PPTX
The Good, The Bad and The Ugly of Event Sourcing
Dennis Doomen
 
PPTX
Practical introduction to DDD, CQRS and Event Sourcing
Dennis Doomen
 
PPTX
Design patterns for Event Sourcing in .NET
Dennis Doomen
 
PPTX
Decomposing the Monolith (Riga Dev Days 2019)
Dennis Doomen
 
PPTX
Decomposing the Monolith using modern-day .NET and a touch of microservices
Dennis Doomen
 
PPTX
How to Practice TDD Without Shooting Yourself in the Foot
Dennis Doomen
 
PPTX
Dennis Doomen. Using OWIN, Webhooks, Event Sourcing and the Onion Architectur...
IT Arena
 
PPTX
How to practice TDD without shooting yourself in the foot
Dennis Doomen
 
PPTX
How To Practice TDD Without Shooting Yourself In The Foot
Dennis Doomen
 
PPTX
A lab around the principles and practices for writing maintainable code
Dennis Doomen
 
PPTX
My first year with event sourcing
Tim Huijzers
 
PDF
CQRS + Event Sourcing
Mike Bild
 
PPTX
Decomposing the monolith into embeddable microservices using OWIN, WebHooks, ...
Dennis Doomen
 
PDF
Design and Implementation of A Data Stream Management System
Erdi Olmezogullari
 
PPTX
A lab around the principles and practices for writing maintainable code (2019)
Dennis Doomen
 
PDF
My first year with event sourcing amersfoort 12-06-2018
Tim Huijzers
 
PPTX
Microsoft SQL Server - StreamInsight Overview Presentation
Microsoft Private Cloud
 
PPTX
Beyond Process Mining: Discovering Business Rules From Event Logs
Marlon Dumas
 
Event Sourcing from the Trenches (with examples from .NET)
Dennis Doomen
 
The Good, The Bad and The Ugly of Event Sourcing
Dennis Doomen
 
The Good, The Bad and The Ugly of Event Sourcing
Dennis Doomen
 
Practical introduction to DDD, CQRS and Event Sourcing
Dennis Doomen
 
Design patterns for Event Sourcing in .NET
Dennis Doomen
 
Decomposing the Monolith (Riga Dev Days 2019)
Dennis Doomen
 
Decomposing the Monolith using modern-day .NET and a touch of microservices
Dennis Doomen
 
How to Practice TDD Without Shooting Yourself in the Foot
Dennis Doomen
 
Dennis Doomen. Using OWIN, Webhooks, Event Sourcing and the Onion Architectur...
IT Arena
 
How to practice TDD without shooting yourself in the foot
Dennis Doomen
 
How To Practice TDD Without Shooting Yourself In The Foot
Dennis Doomen
 
A lab around the principles and practices for writing maintainable code
Dennis Doomen
 
My first year with event sourcing
Tim Huijzers
 
CQRS + Event Sourcing
Mike Bild
 
Decomposing the monolith into embeddable microservices using OWIN, WebHooks, ...
Dennis Doomen
 
Design and Implementation of A Data Stream Management System
Erdi Olmezogullari
 
A lab around the principles and practices for writing maintainable code (2019)
Dennis Doomen
 
My first year with event sourcing amersfoort 12-06-2018
Tim Huijzers
 
Microsoft SQL Server - StreamInsight Overview Presentation
Microsoft Private Cloud
 
Beyond Process Mining: Discovering Business Rules From Event Logs
Marlon Dumas
 
Ad

More from Dennis Doomen (17)

PDF
15 Years of Insights from a TDD Practitioner (NDC Oslo)
Dennis Doomen
 
PPTX
Using Boundary-Driven Development to beat code complexity
Dennis Doomen
 
PPTX
Getting a grip on your code dependencies (2023-10)
Dennis Doomen
 
PPTX
Tools and practices to help you deal with legacy code
Dennis Doomen
 
PPTX
What you can learn from an open-source project with 250 million downloads
Dennis Doomen
 
PPTX
Getting a grip on your code dependencies
Dennis Doomen
 
PPTX
My Laws of Test Driven Development (2023)
Dennis Doomen
 
PPTX
Automate Infrastructure with Pulumi and C#
Dennis Doomen
 
PPTX
What is the right unit in unit testing (UpdateConf 2022)
Dennis Doomen
 
PPTX
50 things software teams should not do.pptx
Dennis Doomen
 
PPTX
What is the right "unit" in unit testing and why it is not a class?
Dennis Doomen
 
PPTX
How to practice TDD without shooting yourself in the foot
Dennis Doomen
 
PPTX
Lessons learned from two decades of professional software development
Dennis Doomen
 
PPTX
Strengths and weaknesses of dependency injection
Dennis Doomen
 
PPTX
Build Libraries That People Love To use
Dennis Doomen
 
PPTX
Decomposing the Monolith using Microservices that don't give you pain
Dennis Doomen
 
PPTX
Build Libraries, Not Frameworks
Dennis Doomen
 
15 Years of Insights from a TDD Practitioner (NDC Oslo)
Dennis Doomen
 
Using Boundary-Driven Development to beat code complexity
Dennis Doomen
 
Getting a grip on your code dependencies (2023-10)
Dennis Doomen
 
Tools and practices to help you deal with legacy code
Dennis Doomen
 
What you can learn from an open-source project with 250 million downloads
Dennis Doomen
 
Getting a grip on your code dependencies
Dennis Doomen
 
My Laws of Test Driven Development (2023)
Dennis Doomen
 
Automate Infrastructure with Pulumi and C#
Dennis Doomen
 
What is the right unit in unit testing (UpdateConf 2022)
Dennis Doomen
 
50 things software teams should not do.pptx
Dennis Doomen
 
What is the right "unit" in unit testing and why it is not a class?
Dennis Doomen
 
How to practice TDD without shooting yourself in the foot
Dennis Doomen
 
Lessons learned from two decades of professional software development
Dennis Doomen
 
Strengths and weaknesses of dependency injection
Dennis Doomen
 
Build Libraries That People Love To use
Dennis Doomen
 
Decomposing the Monolith using Microservices that don't give you pain
Dennis Doomen
 
Build Libraries, Not Frameworks
Dennis Doomen
 

Recently uploaded (20)

PDF
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PDF
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
PDF
The Evolution of KM Roles (Presented at Knowledge Summit Dublin 2025)
Enterprise Knowledge
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PPTX
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
PDF
The Future of Artificial Intelligence (AI)
Mukul
 
PDF
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PDF
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
PDF
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
A Strategic Analysis of the MVNO Wave in Emerging Markets.pdf
IPLOOK Networks
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
The Evolution of KM Roles (Presented at Knowledge Summit Dublin 2025)
Enterprise Knowledge
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
The Future of Artificial Intelligence (AI)
Mukul
 
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
Get More from Fiori Automation - What’s New, What Works, and What’s Next.pdf
Precisely
 
NewMind AI Weekly Chronicles - July'25 - Week IV
NewMind AI
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 

Event Sourcing from the Trenches (DDD Europe 2020)

  • 1. Dennis Doomen | @ddoomen | Aviva Solutions | The Continuous Improver
  • 6. Command Handlers Commands Domain Model Event Store Events App Query Store Data Access Projectors Events Query HTTP API Projections Events Command HTTP API Great unit of testing Great unit of testing Auditability comes for free Can look at the state in the past Can be scaled independently Autonomous projections Aligns well with Event Storming Forces you to understand your domain thoroughly No relational table structure anymore. Can replay old data against new rules More difficult to envisage domain relationships Great for replication
  • 7. Application Command Service Correct Customer Email Handler Customer Unit of Work Projector Data Access Layer Read Database Write Database CorrectCustomerEmailCommand HTTP API / In-process invocation Get<Customer>(identity) Correct Email Event Store Load(events) Apply Get changes CustomerEmailCorrectedEvent Submit changes History Dennis Doomen | @ddoomen | The Continuous Improver NES Aggregates.NET SimpleDomain NStore EventStore NEventStore SQLStreamStore NStore NES Marten Handelier Brighter MediatR (*) Projac LiquidProjections (*)
  • 8. Dennis Doomen | @ddoomen | The Continuous Improver Application Domain NoSQL / RDBMS OR/M / DAL Web UI, HTTP API, etc Lucene Index Document Projector Web UI, HTTP API, etc Web UI, HTTP API, etc Domain Commands Events Event StoreProjections Projectors Uses Event Sourcing Uses traditional CRUD architecture Indexing-based architecture Subcribe to webhooks Coarse- grained HTTP requests. Bus Subscribe Publish coarse- grained event
  • 9. Customer #123 Correct Customer Shipping Address Command Customer Shipping Address Corrected Event Event Store Treat as a message, not a type Order #456 Correct Shipping Address Command Handler Application Customer Shipping Address Corrected Handler Order Redirected Event. Identity != natural key Identify partition key Primitive types only Avoid terms like Create, Update, Delete, Change. Avoid property change events Don’t use as inter-domain contracts Don’t expose outside the domain Dennis Doomen | @ddoomen | The Continuous Improver
  • 10. Customer #123 Correct Customer Shipping Address Command Customer Shipping Address Corrected Event Event Store Order #456 Correct Shipping Address Command Handler Application Order Redirected Event Dennis Doomen | @ddoomen | The Continuous Improver
  • 11. Command Service Some Command Handler Customer #123 Event Store Customer Created Event Get<Customer>(“123”) Customer Created Event Converter Customer Enrolled Event May split or merge events Can also run as part of migration May change the identity Unaffected Events Dennis Doomen | @ddoomen | The Continuous Improver
  • 12. Event Store Projector Projector RDBMS Subscribe Subscribe Document DB Projector RDBMS Subscribe Raw SQLNHibernate RavenDB Lookup Autonomous & independent Storage technique optimized for projection No joining of projections Avoid reusing the projections for multiple purposes Use aggressive caching during rebuilds. Caching strategy optimized for projector Owned by projector Dennis Doomen | @ddoomen | The Continuous Improver Stream-by-stream projections during rebuilds
  • 13. var mapBuilder = new EventMapBuilder<MyContext, DocumentProjection, string>(); mapBuilder .Map<WarrantAssignedEvent>() .AsCreateOf(anEvent => anEvent.Number) .Using((document, anEvent) => { document.Type = "Warrant"; document.Kind = anEvent.Kind; document.Country = anEvent.Country; document.State = anEvent.InitialState; }); mapBuilder .Map<StateTransitionedEvent>() .When(anEvent => anEvent.State != "Closed") .AsUpdateOf(anEvent => anEvent.DocumentNumber) .Using((document, anEvent) => document.State = anEvent.State); Dennis Doomen | @ddoomen | The Continuous Improver
  • 14. Transaction Event Event Transaction Event Event Transaction Event Event RDBMS INSERT/UPDATE … WHERE … Transaction Event Event Transaction Event Event Transaction Event Event RDBMS INSERT/UPDATE … WHERE … INSERT/UPDATE … WHERE … INSERT/UPDATE … WHERE … Unit of Work Dennis Doomen | @ddoomen | The Continuous Improver
  • 15. private async Task<ExceptionResolution> OnException(ProjectionException exception, int attempts) { if (IsTransient(exception)) { if (attempts < 3) { await Task.Delay(TimeSpan.FromSeconds(attempts ^ 2)); return ExceptionResolution.Retry; } return ExceptionResolution.Abort; } else { if (exception.TransactionBatch.Count > 1) { return ExceptionResolution.RetryIndividual; } // Mark projection as corrupt return ExceptionResolution.Ignore; } } Dennis Doomen | @ddoomen | The Continuous Improver
  • 16. Event Store Projector Subscription Projection Subscribes to events from multiple aggregates Lookup
  • 17. Event Store Other Projector Lookup Projector Subscription Subscription Storage (persistent) Lookup Event Modifier Modifies events with lookup data Receives extended events Dennis Doomen | @ddoomen | The Continuous Improver
  • 18. var stats = new ProjectionStats(() => DateTime.UtcNow); stats.StoreProperty("CountByDocument", "some setting key", "some value"); stats.LogEvent("CountByDocument", "some significant thing that happened"); stats.TrackProgress("CountByDocument", currentCheckpoint); float? transactionsPerSecond = stats.GetSpeed("CountByDocument"); TimeSpan? eta = stats.GetTimeToReach("CountByDocument", targetCheckpoint); public void Configure(IAppBuilder builder) { builder.UseStatistics(stats); } Dennis Doomen | @ddoomen | The Continuous Improver
  • 19. IAppBuilder builder = …. builder.UseStatistics(stats); GET http://localhost/projectionStats/CountByDocument { "projectorId": "CountByDocument", "lastCheckpoint": 1000, "lastCheckpointUpdatedUtc": "2018-05-10T10:39:00Z", "properties": [{ "key": "some setting key", "value": "some value", "lastUpdatedUtc": "2018-05-10T10:39:00Z" }], "eventsUrl": "http://localhost/projectionStats/CountByDocument/events" } Dennis Doomen | @ddoomen | The Continuous Improver
  • 20. Document #1 Created Event Event Store Graph Projector Document #1 Closed Event (other events) Projector with active projections Archiving Projector Start archiving Document #1 Marked As Archivable Event Mark all events as archivable Tracks dependencies between documents Deletes projections related to Document #1 Can skip all archivable events during next rebuild. Dennis Doomen | @ddoomen | The Continuous Improver
  • 21. Event Store Lucene Projector Document #1 Marked As Archivable Event Allows projectors to clean up Lucene Index Take snapshot Purge events Tombstone $tombstone stream Application Document Projector Search. Tracks deleted streams for future references Stream Tombstoned Event Search Dennis Doomen | @ddoomen | The Continuous Improver
  • 22. Event Store Projector Application Version 2 Owns schema (e.g. FluentMigrator) Version 1 X Involves down-time until projections are rebuild Dennis Doomen | @ddoomen | The Continuous Improver
  • 23. Event Store Projector Application Application Network Load Balancer Event Store Version 1 Version 2 events Projection ProjectorProjection bring off-line Returns HTTP 503 (Service Unavailable) Dennis Doomen | @ddoomen | The Continuous Improver Returns HTTP 503 (Service Unavailable)
  • 26. Dennis Doomen | @ddoomen | The Continuous Improver
  • 27. Dennis Doomen @ddoomen Dennis Doomen | @ddoomen | The Continuous Improver
  • 28. • The Good, The Bad and the Ugly of Event Sourcing https://www.continuousimprover.com/search/label/event%20sourcing • Effective Aggregate Design (Vaughn Vernon) http://dddcommunity.org/library/vernon_2011/ • Liquid Projections https://www.liquidprojections.net • Distributed Event Sourcing (Slides) https://www.slideshare.net/dennisdoomen/building-occasionally- connected-applications-using-event-sourcing • Data schema changes in an event sourced system (paper) https://files.movereem.nl/2017saner-eventsourcing.pdf