Skip to content

Example: Bank

A bank account is classic example when event sourcing is shown.

Repo

https://github.com/depeche-py/example-bank

Walk through

bank/api

A simple REST API using FastAPI

bank/messages.py

Defines a base class for all messages in the system as well as a couple of command and event messages, e.g.

class CreateAccountCommand(Message):
    account_id: _uuid.UUID | None = None
    account_number: str


class AccountCreatedEvent(Message):
    account_id: _uuid.UUID
    account_number: str

bank/domain.py

The definition of the Domain objects

Account

Account has three operations (create, withdraw, deposit) and tracks the resulting balance.

The operations are implemented in such a way that they just append & apply a new event. The _apply method is called by the inherited apply method. It is the projection that will be applied for each event whenever the state needs to be (re)constructed from them.

class Account(_es.EventSourcedAggregateRoot[_uuid.UUID, _messages.AccountEvent]):
    id: _uuid.UUID
    number: str
    balance: int

    def _apply(self, event: _messages.AccountEvent) -> None:
        if isinstance(event, _messages.AccountCreatedEvent):
            self.id = event.account_id
            self.number = event.account_number
            self.balance = 0
        # over event types...

    @classmethod
    def create(cls, account_id: _uuid.UUID, number: str) -> "Account":
        account = cls()
        account.apply(
            _messages.AccountCreatedEvent(account_id=account_id, account_number=number)
        )
        return account

    #...

Transfer

Is used to keep the state for transfer from one to another Account. Together with the event handlers it can be seen as sort of a process manager.

bank/handlers

commands

Defines a class that handles command messages. It uses repositories to load/save the event-sourced domain objects. The command handler is used both from the REST API and from a subscription on a stream of command messages.

events

Defines classes that handle events. The event handlers are used by subscriptions to event streams.

queries

Defines a class that is used by the REST API to get domain objects.

bank/infra

In this file, all the infrastructure is defined. Most notably, we define:

  • a dependency injection container (using the explicit-di library which is used to simplify the creation of & calls to the handler objects.
  • aggregate streams and subscriptions