Describe the bug
When events are applied to an aggregate to materialize it, the events should be applied in version order to maintain the event history.
The events.AggregateStore use an eh.EventStore to read events and then applies them in the same order that were received from the event store.
The query to read the documents from the event collection provides a filter and no sort option, so the documents are returned in the "natural order" witch as explain by documentation: "This ordering is an internal implementation feature, and you should not rely on any particular ordering of the documents." (according to https://www.mongodb.com/docs/manual/reference/method/cursor.sort/#return-in-natural-order)
func (s *EventStore) Load(ctx context.Context, id uuid.UUID) ([]eh.Event, error) {
cursor, err := s.events.Find(ctx, bson.M{"aggregate_id": id})
...
}
and
func (s *EventStore) LoadFrom(ctx context.Context, id uuid.UUID, version int) ([]eh.Event, error) {
cursor, err := s.events.Find(ctx, bson.M{"aggregate_id": id, "version": bson.M{"$gte": version}})
...
}
To Reproduce
I couldn't reproduce it yet. I think that the current implementation of MongoDB store adds new documents in insertion order, and to insert in a different order you should delete some old documents.
Steps to reproduce the behavior (perhaps):
- Insert a number of events for several aggregates
- Remove the events of one the aggregate
- Insert new events for existent aggregates
- Read events for existent aggregates (one aggregate at a time)
It is possible that the events read for some the aggregates were not in the desired order (the version order).
Expected behavior
The events applied to an aggregate by the events.AggregateStore should be in order of the version number.
Possible solutions
There are two possible solutions to this problem, depending on which component should be responsible of the order:
- The eh.EventStore should guarantee the order of events
- The events.AggregateStore should guarantee the order of applications of events
In the first case, we can simple add a Sort option to the query to ensure the documents are read in the required order.
This uses computing power of the database and should be implemented in all the event store implementations.
In the second case, the events.AggregateStore should order the events before applying them. Because the version number of events is an integer between a and b (a the min version read, and b the max), and b - a should be the exact number of events, we can quickly move the events into an array using the version - a as index.
This uses computing power of the application, but the algorithm is smart enough.
I want to hear some comments and I can provide a PR to solve this.
Describe the bug
When events are applied to an aggregate to materialize it, the events should be applied in version order to maintain the event history.
The
events.AggregateStoreuse aneh.EventStoreto read events and then applies them in the same order that were received from the event store.The query to read the documents from the event collection provides a filter and no sort option, so the documents are returned in the "natural order" witch as explain by documentation: "This ordering is an internal implementation feature, and you should not rely on any particular ordering of the documents." (according to https://www.mongodb.com/docs/manual/reference/method/cursor.sort/#return-in-natural-order)
and
To Reproduce
I couldn't reproduce it yet. I think that the current implementation of MongoDB store adds new documents in insertion order, and to insert in a different order you should delete some old documents.
Steps to reproduce the behavior (perhaps):
It is possible that the events read for some the aggregates were not in the desired order (the version order).
Expected behavior
The events applied to an aggregate by the
events.AggregateStoreshould be in order of the version number.Possible solutions
There are two possible solutions to this problem, depending on which component should be responsible of the order:
In the first case, we can simple add a Sort option to the query to ensure the documents are read in the required order.
This uses computing power of the database and should be implemented in all the event store implementations.
In the second case, the events.AggregateStore should order the events before applying them. Because the version number of events is an integer between
aandb(athe min version read, andbthe max), andb - ashould be the exact number of events, we can quickly move the events into an array using theversion - aas index.This uses computing power of the application, but the algorithm is smart enough.
I want to hear some comments and I can provide a PR to solve this.