If you are used to traditional databases, then to only append and never update your data may sound like a crazy idea. However, not only does this enable historical queries, but also enhances fault tolerance and scalability. In this presentation we briefly describe two immutable data stores (Rich Hickey's Datomic and Greg Young's EventStore) and compare their different data models using an example problem domain. Along the way we learn about CQRS, Aggregates, Projections and why you want your data to be immutable.
EventStore is a data store for applications using event sourcing and time-series data. EventStore runs on .NET and Mono.
Datomic is a database of time-based facts, with declarative queries and ACID transactions. Datomic is written in Clojure and runs on the JVM.
11. Playing the game
Player A
Player B
Server
paper
Player B: paper
Game 123
onsdag 25 september 13
12. Playing the game
Player A
Player B
Server
rock
Player B: paper
Player A: rock
Game 123
onsdag 25 september 13
13. Playing the game
Player A
Player B
Server
Player B: paper
Player A: rock
Game 123
Game 123
winner: Player B
loser: Player A
onsdag 25 september 13
14. Playing the game
Player A
Player B
Server
Player B: paper
Player A: rock
Game 123
Game 123
winner: Player B
loser: Player A
CREATED WAITING
GAME WON
GAME TIED
any move
other move
(victory)
other move
(tie)
onsdag 25 september 13
20. Actions
Create game
Make move
Get game result
POST /games
POST /games/123
move=rock
GET /games/123
1. Form (make move)
2. Waiting
3. Game result
4. Error
onsdag 25 september 13
23. http://geteventstore.com
Runs on .NET and Mono
Free (store) or Commercial (HA)
API
Custom TCP (c#)
ATOM over HTTP (xml/json)
Features
Event streams, projections, generate new events (CEP)
€1500/year
onsdag 25 september 13
30. CREATED WAITING
GAME WON
GAME TIED
any move
if victory
other move
if tie
GameCreatedEvent{:game 123, :creator "player-1", :time 1}
MoveMadeEvent{:game 123, :player "player-1", :move "rock", :time 2}
Current state?
onsdag 25 september 13
31. CREATED WAITING
GAME WON
GAME TIED
any move
if victory
other move
if tie
GameCreatedEvent{:game 123, :creator "player-1", :time 1}
MoveMadeEvent{:game 123, :player "player-1", :move "rock", :time 2}
GameCreatedEvent
Current state?
CREATED
onsdag 25 september 13
32. CREATED WAITING
GAME WON
GAME TIED
any move
if victory
other move
if tie
GameCreatedEvent{:game 123, :creator "player-1", :time 1}
MoveMadeEvent{:game 123, :player "player-1", :move "rock", :time 2}
Current state?
WAITING
MoveMadeEvent
onsdag 25 september 13
33. Aggregates
Scope of consistency when handling a command
Game
+ id
+ state
+ players
+ moves
+ winner
+ loser
Move
+ id
+ move
+ player
Player
+ id
+ name
+ email
onsdag 25 september 13
34. Aggregates as Event Streams
event1 GameCreatedEvent{:game 1...}
event2 MoveMadeEvent{:game 1....}
stream = game-1
version = 2
onsdag 25 september 13
35. Aggregates as Event Streams
event1 GameCreatedEvent{:game 1...}
event2 MoveMadeEvent{:game 1....}
stream = game-1
version = 2
event1 GameCreatedEvent{:game 2...}
event2 MoveMadeEvent{:game 2....}
event3 MoveMadeEvent{:game 2....}
event4 GameWonEvent{:game 2....}
stream = game-2
version = 4
onsdag 25 september 13
57. System with EventStore
1.command Event
Store
Command
Handler
2.get events
3.add events
4.update
projections
onsdag 25 september 13
58. System with EventStore
1.command Event
Store
Command
Handler
2.get events
3.add events
4.update
projections
5.get events
or projections
Some
service
onsdag 25 september 13
59. System with EventStore
1.command Event
Store
Command
Handler
2.get events
6.update state
3.add events
4.update
projections
5.get events
or projections
Some
service
onsdag 25 september 13
60. System with EventStore
1.command Event
Store
Command
Handler
2.get events
6.update state
3.add events
4.update
projections
7.query
5.get events
or projections
Some
service
onsdag 25 september 13
62. http://www.datomic.com/
Runs on JVM
Free (3 peers, local storage) or Commercial (HA, distrib)
Features
ACID transactions, declarative query engine
€2300
onsdag 25 september 13
64. Fact
Something known to have happened or existed
2004-10-01 the email of Jan was ”jan.kronquist@jayway.se”
onsdag 25 september 13
65. Fact
Something known to have happened or existed
2004-10-01 the email of Jan was ”jan.kronquist@jayway.se”
2007-01-01 the email of Jan was ”jan.kronquist@jayway.com”
onsdag 25 september 13
94. Aggregates?
Only by convention
cas (compare and set)
isComponent on relation
Game
+ id
+ state
+ players
+ moves
+ winner
+ loser
Move
+ id
+ move
+ player
onsdag 25 september 13
95. What to find
Where clauses [entity attribute value]
Implicit joins
Call arbitrary function
Query language
onsdag 25 september 13
96. Query example - basic
[:find ?email
:where
[_ :email ?email]]
onsdag 25 september 13
97. Query example - basic
[:find ?email
:where
[_ :email ?email]]
[["jan.kronquist@jayway.com]
["player-1@gmail.com"]
["player-2@gmail.com"]]
onsdag 25 september 13
98. Query example - aggregation
[:find ?state (?count game)
:where
[?game :state ?state]]
onsdag 25 september 13
110. EventStore Events
✓ Understandable by normal people
✓ Designed for integration
✓ Forces aggregate design (scalability)
✓ Capture intent
๏ Require design effort to get right
๏ Complect transaction and query
onsdag 25 september 13
111. Datomic Facts
✓ Support partial information
✓ Normalization support
✓ CRUD out of the box
๏ Static schema
onsdag 25 september 13
112. ✓ New events
✓ New event attributes
✓ Event attributes rename (change deserialization)
✓ Projected state change (rebuild projection)
๏ Cross event refactoring
EventStore schema evolution
onsdag 25 september 13
113. ✓ New or removed attributes
✓ New or removed entity types
✓ Move attributes between entities
๏ Fact attributes rename not possible
๏ Fact attribute type change not possible
Datomic schema evolution
onsdag 25 september 13
114. ✓ Projections use JavaScript
✓ Persistent
๏ Require projection
EventStore queries
onsdag 25 september 13
115. ✓ Declarative
✓ Logic-based
✓ Allows calling out to your own code
๏ New language to learn
Datomic queries
onsdag 25 september 13
116. When to use Event Sourcing?
Domains where events seem natural
Different teams with different models
onsdag 25 september 13
117. When to use Datomic?
Data can be modelled using entities and attributes
History is or may be interesting
onsdag 25 september 13