Second article about playing with event sourcing. You can have a look at the first one here.
I left you with the need to read your model. As you will see my first implementation is straightforward as it consists in iterating through the EventTimeLine, filtering to what we need and mutating an object that is convenient to read. The retrieval method is in PersonRegistry service:
def get_person_by_id(self, demanded_id):
returned_person = None
person_events = (
p for p in self.timeline
if p['personId'] == demanded_id
)
for event in person_events:
if event['type'] == EventTimeLine.PERSON_CREATION:
returned_person = Person(
event['status'],
Address(
event['address']['street'],
event['address']['city']
),
Name(
event['name']['firstname'],
event['name']['lastname']
)
)
if event['type'] == EventTimeLine.PERSON_STATUS_CHANGE:
returned_person.status = event['newStatus']
return returned_person
It works there are obvious drawbacks.
- I have to iterate through the whole EventTimeLine every time I need a person, which will take longer and longer as my timeline will grow (list → O(n) in read).
- I may have to mutate my entity object a lot, for nothing.
EventTimeLine is greate for writing purpose but not so convenient for reading. The solution is to use the events to populate an intermediate data structure with better read access. To do so we can use the Observer pattern. This is for next article.
The repository is updated with model code, tests and a UI wrote using Bottle