I'm building a DDD/CQRS Event Sourcing application. (.NET, EventStore)
I read a lot of articles about it, especially the famous bank account topic.
As reminder, we have the following events sequence:
But I've never found a blog post explaining how to validate the events sequence? I mean, what happen if I receive the Deposited event first, before BankAccountCreated? In other words, how do I check whether the bank account is created? How do I know the stream is in a valid state?
Do I have to call the read-model? every time? in each event? each method of the aggregate? What happen if the user sent it twice and the readmodel is not sync, yet?
I've read a lot of stuff about Event Sourcing, maybe not enough ^^, but I didn't find any information regarding the consistency about the events flow.
In my application, I cannot apply an event if the "first" event (ContactAdded) does not exist. Does it mean I have to call the EventStore each time I need to do something?
Thanks for your help.
There is a lot there.
How do I know the stream is in a valid state?
Each stream should have a monotonically increasing Version number on each event. Event 1 should precede Event 2 etc, per stream (Aggregate). EventStore will ensure this level of consistency by applying optimistic concurrency. You can provide an expected Stream Version (e.g. last Version written) when you write events to Event Store. When you read your stream of Events, you take the last Version number and you pass that along when you write Events to EventStore. If the event stream has grown since you last read, a concurrency error will be raised.
Do I have to call the read-model? every time? in each event? each method of the aggregate?
There is some confusion of terms here. Keep in mind Events vs Commands, Read vs Write models, and what purpose each one serves. You display data from your Read model. You validate and process against your write model.
What happen if the user sent it twice and the readmodel is not sync, yet?
Given the optimistic concurrency policy above, you essentially get a first-in-wins policy. To get past the issue, you can trap concurrency errors and reprocess your command from the beginning (getting the latest state from EventStore).
Does it mean I have to call the EventStore each time I need to do something?
Yes. On each Command, you would read the Event stream for your Aggregate and restore state. You can use Snapshots as an optimization, but the concept remains the same.