Year with EventSourcing & CQRS
as web is growing
in complexity and size
simple CMS
simple webshops
existing practices
MVC
CRUD
existing practices
Clean architecture vs performance
id | 123 |
---|---|
title | Register button doesnt work in IE |
assigned | null |
type | BUG |
status | OPEN |
priority | URGENT |
createdAt | 2016-03-11 22:22:11 |
updatedAt | 2018-01-27 08:01:35 |
closedAt |
Issue tracker: Issue
What if we record all changes?
IssueCreated(123, 'Something', 'text', BUG, NORMAL, ' 2016..')
IssueAssigned(123, TeamManager, ' 2016-03-12 10:00:00')
PriorityChanged(123,URGENT, ' 2016-08-11 15:46:33')
IssueDellocated(123,'2016...')
IssueClosed(123,'2016...')
IssueReopened(123, ' 2018-01-27 08:01:35')
TitleChanged(123, ' Register button doesnt work in IE', '2016...')
and create state from applying them?
event sourcing
issue
678
number of issues opened today
abc123-123-121313
daa-2-2-3-3-2-3-2
unassigned urgent issue ids
abc-123-23 Login doesnt work 85
acd-342-43 Bug X 75
open issues with number of comments
Command Query Responsibility Segregation
Miro Svrtan
trainer / senior developer / contractor
ZgPHP organizer
@msvrtan
My ES + CQRS experience
2 years Year with EventSourcing & CQRS
project X
devboard
External concerts on TicketSwap
Defining bounded context
You as a TicketSwap user:
- can sell tickets
- can buy tickets
- just use the site
In "boring" domain
In a startup
Concentrate on bringing value not perfect code
Saga/process manager
Queues
And worst enemy
Your best friend
Eventual consistency
- never blindly trust your read model data
- aggregates are ONLY source of truth
Domain - application - infrastructure separation
Saving invoice into RDBMS
blog post + comments
in NoSQL
Domain - application - infrastructure separation
Writing tests
Skip ES + CQRS if no testing experience
Writing tests
- don't test state of aggregate
- concentrate on unit/integration testing
- do some end-to-end tests
Mock the infrastructure
- not locked to infrastructure while developing
- 10-100x faster testing
Performance
Loading aggregate
<10 events 10 ms
~50 events 20 ms
~100 events 50 ms
~2000 events 1500 ms
Big aggregate root example
- ~700 entities inside
- 650.000 events
Snapshotting
Snapshotting DIY
- creates a snapshot every ~200 events
- 17Mb of payload
- aggregate load time < 100ms
UUIDs
UUID performance
"64c3e987-905a-4426-8dc3-ddb61650b86b"
vs
123456
Class number explosion
- UserController
- User (Entity)
- UserRepository
- UserController
- RegisterUserCommand
- UserCommandHandler
- User (Aggregate)
- UserRepository
- UserRegisteredEvent
- UserReadProjector
- UserReadEntity
- UserReadRepository
Class number explosion
- UserController
- User (Entity)
- UserRepository
- UserController
- RegisterUserCommand
- ChangePasswordCommand
- UserCommandHandler
- User (AggregateRoot)
- UserRepository
- UserRegisteredEvent
- PasswordChangedEvent
- UserReadProjector
- UserReadEntity
- UserReadRepository
No read side logic
Building read side:
replaying events
Use familiar tech
ES+CQRS is a big shift in thinking
Final words
@msvrtan
Any questions?
Year with EventSourcing and CQRS
By Miro Svrtan
Year with EventSourcing and CQRS
Slides for my 'Year with EventSourcing and CQRS' on PHP Benellux conference (2018-01-27)
- 2,418