Skip to content

Commit da9a09d

Browse files
committed
v2
1 parent fca9289 commit da9a09d

27 files changed

+357
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ out/
3535

3636
### VS Code ###
3737
.vscode/
38+
!.vscode/settings.json

.vscode/settings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"plantuml.exportFormat": "png",
3+
"plantuml.exportSubFolder": false,
4+
"plantuml.exportOutDir": "img",
5+
"plantuml.render": "PlantUMLServer",
6+
"plantuml.server": "http://localhost:18181/",
7+
// docker run --rm -p 18181:8080 plantuml/plantuml-server:tomcat
8+
"auto-rename-tag.activationOnLanguage": ["html", "xml"]
9+
}

README.md

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,68 +23,83 @@
2323

2424
## <a id="0b79795d3efc95b9976c7c5b933afce2"></a>Introduction
2525

26-
PostgreSQL is the world's most advanced open source database. Also, PostgreSQL is suitable for Event
27-
Sourcing.
26+
Usually, our applications operate with the current state of a domain object. But sometimes, we need to know the entire history of the domain object changes. For example, we want to know how an order got into its current state.
27+
28+
We can store all changes to the domain object state as a sequence of events in an append-only event stream. Thus, event streams will contain an entire history of changes. But how can we be sure that this history is authentic and free from errors? We can use event streams as a primary source of truth in a system. To get the current state of an object, we have to replay all events in the order of occurrence. This pattern is called event sourcing. Database for storing the event streams is called even store.
29+
30+
There are specialized databases for event sourcing. Developer Advocates working for the companies behind these specialized databases tell you that you shouldn't implement event sourcing with traditional relational or document-oriented databases. Is it true or just a marketing ploy? In fact, you can implement event sourcing with any database. The repositories in this series provide samples of event sourced systems that use different databases as event store.
31+
32+
PostgreSQL is the world's most advanced open source database. Also, PostgreSQL is suitable for event
33+
sourcing.
2834

2935
This repository provides a sample of event sourced system that uses PostgreSQL as event store.
3036

3137
![PostgreSQL Logo](img/potgresql-logo.png)
3238

3339
See also
3440

35-
* [Event Sourcing with Kafka and ksqlDB](https://github.com/evgeniy-khist/ksqldb-event-souring)
3641
* [Event Sourcing with EventStoreDB](https://github.com/evgeniy-khist/eventstoredb-event-sourcing)
42+
* [Event Sourcing with Kafka and ksqlDB](https://github.com/evgeniy-khist/ksqldb-event-souring)
3743

3844
## <a id="8753dff3c2879207fa06ef1844b1ea4d"></a>Example Domain
3945

40-
This sample uses heavily simplified ride hailing domain model inspired
41-
by [tech/uklon](https://careers.uklon.ua/) experience.
46+
This sample uses a simple domain model inspired by my work experience in a ride-hailing company.
4247

4348
* A rider can place an order for a ride along a route specifying a price.
49+
* A rider can edit order price to pay more instead of waiting in cases of very high demand.
4450
* A driver can accept and complete an order.
4551
* An order can be cancelled before completion.
4652

47-
![Domain use case diagram](img/domain-1.png)
53+
![Domain use case diagram](img/plantuml/domain-1.png)
4854

49-
![Domain state diagram](img/domain-2.png)
55+
![Domain state diagram](img/plantuml/domain-2.png)
5056

51-
## <a id="19025f75ca30ec4a46f55a6b9afdeba6"></a>Event Sourcing and CQRS 101
57+
## <a id="19025f75ca30ec4a46f55a6b9afdeba6"></a>Event Sourcing and CQRS basics
5258

5359
### <a id="436b314e78fec59a76bad8b93b52ee75"></a>State-Oriented Persistence
5460

55-
![State-oriented persistence](img/es-cqrs-state-oriented-persistence.png)
61+
![State-oriented persistence](img/plantuml/es-cqrs-state-oriented-persistence.png)
5662

5763
### <a id="c4b3d1c8edab1825366ac1d541d8226f"></a>Event Sourcing
5864

5965
Event sourcing persists the state of an entity as a sequence of immutable state-changing events.
6066

61-
![Event sourcing](img/event-sourcing-1.png)
67+
![Event sourcing](img/plantuml/event-sourcing-1.png)
6268

6369
Whenever the state of an entity changes, a new event is appended to the list of events.
6470

65-
![Event sourcing](img/event-sourcing-2.png)
71+
![Event sourcing](img/plantuml/event-sourcing-2.png)
6672

6773
Current state of an entity can be restored by replaying all its events.
6874

69-
Event sourcing is best suited for short-living entities with relatively small total number of
70-
event (like orders).
75+
An entity in event sourcing is also referenced as an **aggregate**.
76+
77+
A sequence of events for the same aggregate are also referenced as a **stream**.
78+
79+
Event sourcing is best suited for short-living entities with a small total number of
80+
events (e.g. orders).
7181

7282
Restoring the state of the short-living entity by replaying all its events doesn't have any
7383
performance impact. Thus, no optimizations for restoring state are required for short-living
7484
entities.
7585

76-
For endlessly stored entities (like users or bank accounts) with thousands of events restoring state
86+
For endlessly stored entities (e.g. users, bank accounts) with thousands of events restoring state
7787
by replaying all events is not optimal and snapshotting should be considered.
7888

89+
### Snapshotting
90+
7991
Snapshotting is an optimization technique where a snapshot of the aggregate's state is also saved,
8092
so an application can restore the current state of an aggregate from the snapshot instead of from
8193
scratch.
8294

83-
![Snapshotting in event souring](img/event-sourcing-snapshotting.png)
95+
On every *nth* event, make an aggregate snapshot by storing an aggregate state and its version.
96+
97+
To restore an aggregate state:
8498

85-
An entity in event sourcing is also referenced as an aggregate.
99+
1. first read the latest snapshot,
100+
2. then read events forward from the original stream starting from the version pointed by the snapshot.
86101

87-
A sequence of events for the same aggregate are also referenced as a stream.
102+
![Snapshotting in event souring](img/plantuml/event-sourcing-snapshotting.png)
88103

89104
### <a id="b2cf9293622451d86574d2973398ca70"></a>CQRS
90105

@@ -94,14 +109,14 @@ processed by different handlers.
94109

95110
A command generates zero or more events or results in an error.
96111

97-
![CQRS](img/cqrs-1.png)
112+
![CQRS](img/plantuml/cqrs-1.png)
98113

99114
CQRS is a self-sufficient architectural pattern and doesn't require event sourcing.
100115

101116
Event sourcing is usually used in conjunction with CQRS. Event store is used as a write database and
102117
SQL or NoSQL database as a read database.
103118

104-
![CQRS](img/cqrs-2.png)
119+
![CQRS](img/plantuml/cqrs-2.png)
105120

106121
Events in event sourcing are a part of a bounded context and should not be used "as-is" for
107122
integration with other bounded contexts. Integration events representing the current state of an
@@ -120,6 +135,9 @@ change events.
120135
* Ability to put the system in any prior state (e.g. for debugging).
121136
* Read-side projections can be created as needed (later) from events. It allows responding to future
122137
needs and new requirements.
138+
139+
The majority of developers I interviewed highlight having a true history of the system as the main advantage
140+
of event sourcing.
123141

124142
## <a id="70b356f41293ace9df0d04cd8175ac35"></a>Requirements for Event Store
125143

img/cqrs-1.png

-87.2 KB
Binary file not shown.

img/cqrs-2.png

-121 KB
Binary file not shown.

img/domain-1.png

-26.9 KB
Binary file not shown.

img/domain-2.png

-33.8 KB
Binary file not shown.
-71.3 KB
Binary file not shown.

img/event-sourcing-1.png

-110 KB
Binary file not shown.

img/event-sourcing-2.png

-79.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)