Skip to content

Instantly share code, notes, and snippets.

@gregoryyoung
Created February 12, 2023 10:43
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregoryyoung/86b4daa731fa6377b3b83d4ad5a1fb24 to your computer and use it in GitHub Desktop.
Save gregoryyoung/86b4daa731fa6377b3b83d4ad5a1fb24 to your computer and use it in GitHub Desktop.
An event-sourced aggregate is a design pattern that allows you to build a system based on events, in which changes to the state of an aggregate are recorded as a series of events. Here's an example of what the code for an event-sourced aggregate might look like in Python:
python
Copy code
class Event:
def __init__(self, data):
self.data = data
class Aggregate:
def __init__(self, events=None):
self._events = []
self._version = -1
if events:
for event in events:
self._apply_event(event)
def apply_event(self, event):
self._version += 1
self._apply_event(event)
self._events.append(event)
def _apply_event(self, event):
method = '_on_' + type(event).__name__
getattr(self, method)(event)
class BankAccount(Aggregate):
def __init__(self, events=None):
self._balance = 0
super().__init__(events)
def deposit(self, amount):
self.apply_event(DepositEvent({
'amount': amount,
}))
def withdraw(self, amount):
if self._balance < amount:
raise ValueError("Not enough funds")
self.apply_event(WithdrawEvent({
'amount': amount,
}))
def _on_DepositEvent(self, event):
self._balance += event.data['amount']
def _on_WithdrawEvent(self, event):
self._balance -= event.data['amount']
class DepositEvent(Event):
pass
class WithdrawEvent(Event):
pass
In this example, the Aggregate class represents the basic structure of an event-sourced aggregate. It keeps track of a list of events, a version number, and provides methods for applying events and updating the state of the aggregate.
The BankAccount class is a concrete implementation of an aggregate that represents a bank account. It has a balance, and provides methods for depositing and withdrawing funds.
The Event class is a simple base class for events that provides a data field to store information about the event. The DepositEvent and WithdrawEvent classes are concrete implementations of events that can be used to change the state of the BankAccount aggregate.
When an event is applied to the BankAccount aggregate, the Aggregate class calls a method with the same name as the event class, prefixed with _on_, to update the state of the aggregate. This is a simple example of event handling, and in a real-world application, you might want to use a more sophisticated mechanism to handle events.
Some important considerations when designing an event-sourced aggregate include:
Atomicity: All changes to the state of an aggregate should be made atomically, in a single operation, to ensure that the aggregate remains in a consistent state at all times.
Idempotency: It should be possible to apply the same event multiple times to the aggregate without causing any harm, to ensure that events are processed correctly even if they are duplicated or arrive out of order.
Event sourcing: Events should be used as the primary source of truth for the state of the aggregate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment