NEventStore issue with repeat events

We use CQRS + ES. ES is NEventStore (folrmerly JOliver EventStore). We have 2 units in different teams. The projections of the second AR depend on the data recorded by the first AR projections in the reading model. The problem is that when we run the software, everything goes so fast that sometimes two aggregates are stored in the event store with the same date-time (CommitStamp column). When playing events, we get them from the very beginning, ordered by the CommitStamp column. But if two threads with the same CommitStamp are taken in the wrong order, projected models blow exceptions.

Any idea how to solve this problem?

=================================

Here is a discussion of this issue on github https://github.com/NEventStore/NEventStore/issues/170

=================================

EDIT . So we are currently reproducing events. I looked for how GetFrom (...) works, and it turned out that commitstamp is not used to commit the column. In the end, there is no fixation order. Therefore, if I start replaying events, he can return the event from today, the next event recorded 2 years ago, the next, etc.

public void ReplayEvents(Action<List<UncommittedEvent>> whatToDoWithEvents, DateTime loadEventsAfterDate) { var eventPortion = store.Advanced.GetFrom(loadEventsAfterDate); var uncommitedEventStream = new UncommittedEventStream(); foreach (var commit in eventPortion) { foreach (var eventMessage in commit.Events.ToList())) { uncommitedEventStream.Append(new UncommittedEvent(eventMessage.Body)); } } whatToDoWithEvents(uncommitedEventStream.ToList()); } 
+6
source share
3 answers

Damian added a control column to the database. This is in the current main branch. When the events that are played using GetFromCheckpoint(int) are true.

+1
source

In NEventStore, the boundary of consistency is a stream. Starting with version 3.2 (as @Marijn mentioned, issue # 159 ), the CommitSequence column is used to organize CommitMessages (and the contained EventMessages) when reading from a stream through all stability engines.

EventMessage ordering is guaranteed on a per-thread basis. There is no implicit ordering of messages across streams. Any actual ordering that may arise as a result, some aspect of the chosen persistence mechanism, is random and cannot be relied on.

To ensure that streamlining will strictly limit the distributed aspects of the library. Even if we considered such a function, it would have to work with all the supported stability mechanisms, including NoSQL stores.

If you are practicing Domain Driven Design, where each thread is a cumulative root, and you need to guarantee order in two or more aggregates, this indicates a design problem in your domain model.

If your forecasts should combine values ​​from several sources (flows), you can count on an order inside the source, but you need to be flexible when ordering between sources. You should also consider the possibility of duplicate messages, especially if you are replaying through an external bus or queue.

If you try to re-order multiple threads at the end of the receiver using a timestamp (CommitStamp), this will be fragile. Timestamps have a fixed resolution (ms, tick, etc.). Even with one writer, everything can happen "at the same time."

+3
source

At the database level, while CommitStamp is suitable for filtering, the CommitSequence column is the one that should determine the order.

As for what translates from the point of view of API calls to any version of libs that you use, I will leave this as an exercise for you (or if you fill out a code snippet and / or a version link, maybe someone else can intervene)

0
source

Source: https://habr.com/ru/post/948764/


All Articles