Skip to content

Instantly share code, notes, and snippets.

@gregoryyoung
Created February 12, 2023 10:43

Revisions

  1. gregoryyoung created this gist Feb 12, 2023.
    68 changes: 68 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    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