@@ -44,7 +44,7 @@ An audit trail may be a regulatory or business requirement.
4444
4545We can store all changes to the domain object state as a sequence of events in an append-only event stream.
4646Thus, event streams will contain an entire history of changes.
47- But how can we be sure that this history is authentic and free from errors ?
47+ But how can we be sure that this history is authentic and error- free?
4848We can use event streams as a primary source of truth in a system.
4949To get the current state of an object, we have to replay all events in the order of occurrence.
5050This pattern is called event sourcing. The database for storing the event streams is called even store.
@@ -91,7 +91,7 @@ This sample uses a simplified domain model of the ride-hailing system.
9191### <a id =" 3-1 " ></a >State-oriented persistence
9292
9393State-oriented persistence (CRUD) applications store only the latest version of an entity.
94- Entities are presented by database records .
94+ Database records present entities .
9595When an entity is updated, the corresponding database record gets updated too.
9696SQL ` INSERT ` , ` UPDATE ` and ` DELETE ` statements are used.
9797
@@ -109,7 +109,7 @@ Events are immutables, so SQL `UPDATE` and `DELETE` statements are not used.
109109
110110![ Event sourcing] ( img/event-sourcing-2.svg )
111111
112- Current state of an entity can be restored by replaying all its events.
112+ The current state of an entity can be restored by replaying all its events.
113113
114114Event sourcing is closely related to domain-driven design (DDD) and shares some terminology.
115115
@@ -118,14 +118,14 @@ An entity in event sourcing is called an **aggregate**.
118118A sequence of events for the same aggregate is called a ** stream** .
119119
120120Event sourcing is best suited for short-living entities with a small total number of
121- events (e.g. orders).
121+ events (e.g., orders).
122122
123123Restoring the state of the short-living entity by replaying all its events doesn't have any
124124performance impact. Thus, no optimizations for restoring state are required for short-living
125125entities.
126126
127- For endlessly stored entities (e.g. users, bank accounts) with thousands of events restoring state
128- by replaying all events is not optimal and snapshotting should be considered.
127+ For endlessly stored entities (e.g., users, bank accounts) with thousands of events restoring state
128+ by replaying all events is not optimal, and snapshotting should be considered.
129129
130130### <a id =" 3-3 " ></a >Snapshotting
131131
@@ -144,8 +144,8 @@ To restore an aggregate state:
144144
145145### <a id =" 3-4 " ></a >Querying the data
146146
147- It's easy to find an aggregate by ID but other queries are difficult.
148- As far as aggregates are stored as append-only lists of immutable events,
147+ It's easy to find an aggregate by ID, but other queries are difficult.
148+ Since aggregates are stored as append-only lists of immutable events,
149149querying the data using SQL, as we used to, is impossible.
150150To find an aggregate by some field, we need to first read all the events and replay them to restore all the aggregates.
151151
@@ -174,8 +174,8 @@ A command generates zero or more events or results in an error.
174174![ CQRS] ( img/cqrs-1.svg )
175175
176176CQRS is a self-sufficient architectural pattern and doesn't require event sourcing.
177- But in practice event sourcing is usually used in conjunction with CQRS.
178- Event store is used as a write database and SQL or NoSQL database as a read database.
177+ But in practice, event sourcing is usually used in conjunction with CQRS.
178+ Event store is used as a write database, and SQL or NoSQL database as a read database.
179179
180180![ CQRS with event sourcing] ( img/cqrs-2.svg )
181181
@@ -186,7 +186,7 @@ Event processing is done by **event handles**.
186186As a part of event processing, we may need to update projections,
187187send a message to a message broker, or make an API call.
188188
189- There are 2 types of event handles: ** synchronous** and ** asynchronous** .
189+ There are two types of event handles: ** synchronous** and ** asynchronous** .
190190
191191Storing the write model and read model in the same database allows for transactional updates of the read model.
192192Each time we append a new event, the projection is updated ** synchronously** in the same transaction.
@@ -218,7 +218,7 @@ The integration event represents the current state of an aggregate, not just cha
218218
219219### <a id =" 3-9 " ></a >Advantages of event sourcing
220220
221- * Having a true history of the system (audit and traceability).
221+ * A true history of the system (audit and traceability).
222222 An industry standard for implementing audit trail.
223223* Ability to put the system in any prior state (e.g. for debugging).
224224* New read-side projections can be created as needed (later) from events.
@@ -360,7 +360,7 @@ and processes them:
360360 WHERE SUBSCRIPTION_NAME = :subscriptionName
361361 FOR UPDATE SKIP LOCKED
362362 ```
363- 2. fetch new events
363+ 2. read new events
364364 ```sql
365365 SELECT e.ID,
366366 e.TRANSACTION_ID::text,
@@ -391,11 +391,11 @@ The `ID` column of the `ES_EVENT` table is of type `BIGSERIAL`.
391391It' s a notational convenience for creating ID columns having their default values assigned from a ` SEQUENCE` generator.
392392
393393PostgreSQL sequences can' t be rolled back.
394- `SELECT nextval(' ES_EVENT_ID_SEQ' )` increments the sequence value and returns it .
394+ `SELECT nextval(' ES_EVENT_ID_SEQ' )` increments and returns the sequence value.
395395Even if the transaction is not yet committed, the new sequence value becomes visible to other transactions.
396396
397397If transaction #2 started after transaction #1 but committed first,
398- the event subscription processor can fetch the events created by transaction #2, update the last processed event ID,
398+ the event subscription processor can read the events created by transaction #2, update the last processed event ID,
399399and thus lose the events created by transaction #1.
400400
401401
@@ -450,7 +450,7 @@ from the Spring Integration.
450450After restarting the backend, existing subscriptions will only process new events after the last processed event
451451and not everything from the first one.
452452
453- New subscriptions (event handlers) in the first poll will fetch and process all events.
453+ New subscriptions (event handlers) in the first poll will read and process all events.
454454Be careful, if there are too many events, they may take a long time to process.
455455
456456# ## <a id="4-9"></a>Class diagrams
@@ -479,7 +479,7 @@ Using PostgreSQL as an event store has a lot of advantages, but there are also d
479479 Integration events are delivered with ** at- least- once** delivery guarantee.
480480 The exactly- once delivery guarantee is hard to achieve due to a dual- write.
481481 A dual- write describes a situation when you need to atomically update the database and publish messages
482- and two- phase commit (2PC) is not an option .
482+ without two- phase commit (2PC).
483483 Consumers of integration events should be idempotent and filter duplicates and unordered events.
4844842 . The asynchronous event handling results in the ** eventual consistency between the write model and sent integration events** .
485485 The polling database table for new events with a fixed delay introduces a full consistency lag
0 commit comments