Race Conditions in triggered events in CQRS

Hi,
I’m building a system using CQRS pattern with the write model depending on EventStore DB, I have an aggregate root which contains three sub entities, each entity can be updated separately, e.g I can do the following commands separately (Create, UpdateA, UpdateB, UpdateC).

Of course after each command I trigger an event for the EventStore and the same for the read model to update its model props.

I need to add “Copy” command, so I thought to clone the aggregate root and trigger an event for each part (entity), so the copy will be as the following:

  • Clone the whole root with the sub entities.
  • Trigger Create event.
  • Trigger AUpdated event.
  • Trigger BUpdated event.
  • Trigger CUpdated event.

I thought this is better and more consistent than triggering one event contains ALL the root with its sub entities.

Now the issue is, some times I receive AUpdate, B, C before the Create event, in the read model, so will not be able to execute the updates because the create never happened and there’s no element with the Id comes with the “updated” events.

What is a good solution for this case or similar cases where I can’t guarantee the order of the events?

Is this a “Saga” ?
Is it a good solution to check (when I receive the Updated items) if the item exists I continue the update, if not, I create an empty one with only the Id and continue the update?

Good day @A.Dabbas and welcome to the Particular discussion group.

Isn’t the read model handled through projections in EventStore? IN which case it’ll be a projection responsibility to handle concurrency, and IIRC it’s supported.

Let me know if I’m missing something.
.m

You’re correct, it’s handled through projections, but I don’t think it guarantees the ordering of events.

It seems to be handled via OCC and idempotency support if possible.

This is not that different from what you would manually do using a saga or by simply handling events out of order (that is my favorite option when doable)

Sorry I’m not that expert in EventStore or NServiceBus, it’s my first time, so how receiving not ordered events in the read model will be taken care of by EventStore and not my system?

No worries. EventStore uses version identifiers in events to determine the order in which events have been published. If the events are reaching the projection engine not in the expected order, e.g., 1342 instead of 1234, events will be reordered using the version number. Not all streams need to be ordered though. For example, in the stock market if you are interested in the current value of a stock you don’t care about the order in which the value changed over time. A different story if you care about the history of a stock, the order is important in this second scenario.

The same approach can be manually applied when using NServiceBus and messages, the message can contain a version number and the handler can reject a message because it’s not aligned with the version it’s expecting to process next.