EDA Patterns
Explore the event patterns: event notifications, event-carried state transfer, and event sourcing.
We'll cover the following
Three different uses or patterns exist that can be called EDA individually or altogether, as follows:
Event notifications
Event-carried state transfer
Event sourcing
Event notifications
Events can be used to notify something has occurred within our application. A notification event typically carries the absolute minimum state, perhaps even just the identifier (ID) of an entity or the exact time of the occurrence of their payload. Components that are notified of these events may take any action they deem necessary. Events might be recorded locally for auditing purposes, or the component may make calls back to the originating component to fetch additional relevant information about the event.
Example
Let’s see an example of PaymentReceived
as an event notification in Go, as follows:
type PaymentReceived struct {PaymentID string}
Here is how that notification might be used:
The above image shows the PaymentReceived
notification being received by two different services. While ServiceA only needed to be notified of the event, ServiceB requires additional information and must make a call back to the Payments service to fetch it.
Event-carried state transfer
Event-carried state transfer is an asynchronous cousin to representational state transfer (REST). In contrast with REST’s on-demand pull model, event-carried state transfer is a push model where data changes are sent out to be consumed by any components that might be interested. The components may create their own local cached copies, negating any need to query the originating component to fetch any information to complete their work.
Example
Let’s see an example of PaymentReceived
as an event-carried state transfer, as follows:
type PaymentReceived struct {PaymentID stringCustomerID stringOrderID stringAmount int}
In this example for event-carried state transfer, we’ve included some additional IDs and an amount collected, but more detail could be added to provide as much detail as possible, as illustrated in the following diagram:
When the PaymentReceived
event is sent with additional information, it changes how downstream services might react to it. We can see in the above image that ServiceB no longer needs to call the Payments service because the event it has received already contains everything it requires.
Event sourcing
Instead of capturing changes as irreversible modifications to a single record, those changes are stored as events. These changes or streams of events can be read and processed to recreate the final state of an entity when it is needed again.
How it works
When we use event sourcing, we store the events in an event store rather than communicating them with other services, as illustrated in the following diagram:
In the above figure, we see that the entire history of our data is kept as individual entries in the event store. When we need to work with a payment in the application, we would read all the entries associated with that record and then perform a left fold of the entries to recreate the final state.