Event Store

We know that the creation of a RoastSchedule Aggregate means persisting it. This is where the Repository pattern comes into play. Since we are going to use Event Sourcing, our concrete RoastSchedule Repository will look slightly different from the traditional Collection-Oriented and Persistence-Oriented Repositories discussed by Vaughn Vernon in Implementing Domain-Driven Design. Our generic Repository Interface will, however, look very similar to a Persistence-Oriented Repository in that it requires a call to Save() to actually push objects down to storage.

public interface IRepository<T> where T : AggregateRoot, new() {
    void Save(AggregateRoot aggregate, int exptectedVersion);
    T GetById(Guid id);

We won’t worry about the generic type constraint new() (requiring that the concrete RoastSchedule have a public constructor public RoastSchedule()) for right now, as it has to do with the way that we re-constitute Aggregates using our Event Sourced Aggregate Root from our Repository.

Now that we have our generic Repository, we are going to design a concrete Repository for an Event Sourced Aggregate. This is where we introduce the idea of an Event Store. Our Event Store is going to be the book of truth for our Event Sourced Aggregates, like RoastSchedule. This will be pretty much a copy/paste from Greg Young’s SimpleCQRS’s in-memory Event Store implementation found here: https://github.com/gregoryyoung/m-r/blob/master/SimpleCQRS/EventStore.cs. It’ll only be temporary until we start looking at real Event Storage tools out there.

Notice that IEventStore has two methods: SaveEvents and GetEventsForAggregate:

public interface IEventStore {
    void SaveEvents(Guid aggregateId, IEnumerable<Event> events, int expectedVersion);
    List<Event> GetEventsForAggregate(Guid aggregateId);

We want to have the RoastScheduleCreated Domain Event that is emitted from our RoastSchedule Aggregate as a result of the CreateRoastSchedule Command persist to our in-memory Event Store. We also want to have the ability to replay all previous Domain Events emitted by the RoastSchedule Aggregate to build the state of the RoastSchedule Aggregate.

Notice the expectedVersion parameter to Save in our IRepository<T> and SaveEvents in our IEventStore interfaces. This is one of the bigger differences between this and a more traditional Repository; this idea of version. When we’re storing Domain Events with the intention to be able to use them to figure out the state of an Aggregate, sequence becomes important. You only have to imagine debits and credits to a bank account being replayed in a different order to understand the issue.

Further, we have named the parameter expectedVersion. When we try to save an Event to the Event Store, we can ask the Event Store what version the Aggregate should be at this moment. This is a check against the Event Store to make sure that the Event we are saving to it is truly the next one to be applied to the Aggregate; hence expectedVersion.

I’ll show you how we use the Event Store and Repository in accordance with our Aggregate Root over the next couple posts.

continue reading…


I will be releasing most of this content only to subscribers. Make sure you sign up by clicking the big red button!

Related Posts:

comments powered by Disqus