🎛️ Event Sourcing
Building blocks
Event Sourcery provides a few building blocks to work with event sourcing.
These are Aggregate and Repository base classes.
Usage
You start from defining your own aggregate inheriting from Aggregate.
There are three required attributes that need to be defined:
category
class-level constant that will be added to all streams from all aggregates of this type__init__
if defined, must not accept any arguments__apply__
method that will change internal state of the aggregate based on the event applied during reading state from the event store
from event_sourcery.event_sourcing import Aggregate, Repository
from event_sourcery.event_store import Event
class SwitchedOn(Event):
pass
class LightSwitch(Aggregate):
category = "light_switch" # 1
def __init__(self) -> None: # 2
self._switched_on = False
def __apply__(self, event: Event) -> None: # 3
match event:
case SwitchedOn():
self._switched_on = True
case _:
raise NotImplementedError(f"Unexpected event {type(event)}")
def switch_on(self) -> None:
if self._switched_on:
return # no op
self._emit(SwitchedOn())
To work with aggregate, you need to create repository. You need an instance of EventStore to do so:
From now on, regardless if you want to work with a given aggregate for the first time or load existing one, you should use repository.aggregate
context manager: