Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS, Event-Sourcing and Web-Applications

As I am reading some CQRS resources, there is a recurrent point I do not catch. For instance, let's say a client emits a command. This command is integrated by the domain, so it can refresh its domain model (DM). On the other hand, the command is persisted in an Event-Store. That is the most common scenario.

1) When we say the DM is refreshed, I suppose data is persisted in the underlying database (if any). Am I right ? Otherwise, we would deal with a memory-transient model, which I suppose, would not be a good thing ? (state is not supposed to remain in memory on server side outside a client request).

2) If data is persisted, I suppose the read-model that relies on it is automatically updated, as each client that requests it generates a new "state/context" in the application (in case of a Web-Application or a RESTful architecture) ?

3) If the command is persisted, does that mean we deal with Event-Sourcing (by construct when we use CQRS) ? Does Event-Sourcing invalidate the database update process ? (as if state is reconstructed from the Event-Store, maintaining the database seems useless) ?

Does CQRS only apply to multi-databases systems (when data is propagated on separate databases), and, if it deals with memory-transient models, does that fit well with Web-Applications or RESTful services ?

like image 548
Rénald Avatar asked Jan 08 '23 00:01

Rénald


2 Answers

1) As already said, the only things that are really stored are the events. The only things that commands do are consistency checks prior to the raise of events. In pseudo-code:

public void BorrowBook(BorrowableBook dto){
    if (dto is valid)
        RaiseEvent(new BookBorrowedEvent(dto))
    else
        throw exception
}

public void Apply(BookBorrowedEvent evt) {
    this.aProperty = evt.aProperty;
    ...
}

Current state is retrieved by sequential Apply. Since this, you have to point a great attention in the design phase cause there are common pitfalls to avoid (maybe you already read it, but let me suggest this article by Martin Fowler).

So far so good, but this is just Event Sourcing. CQRS come into play if you decide to use a different database to persist the state of an aggregate. In my project we have a projection that every x minutes apply the new events (from event store) on the aggregate and save the results on a separate instance of MongoDB (presentation layer will access to this DB for reading). This model is clearly eventually consistent, but in this way you really separate Command (write) from Query (read).

2) If you have decided to divide the write model from the read model there are various options that you can use to make them synchronized:

  • Every x seconds apply events from the last checkpoint (some solutions offer snapshot to avoid reapplying of heavy commands)
  • A projection that subscribe events and update the read model as soon event is raised

3) The only thing stored are the events. Infact we have an event-store, not a command store :)

Is database is useless? Depends! How many events do you need to reapply for take the aggregate to the current state? Three? Maybe you don't need to have a database for read-model

like image 136
BAD_SEED Avatar answered Jan 10 '23 15:01

BAD_SEED


The thing to grok is that the ONLY thing stored is the events*. The domain model is rebuilt from the events.

So yes, the domain model is memory transient as you say in that no representation of the domain model is stored* only the events which happend to the domain to put the model in the current state.

When an element from the domain model is loaded what happens is a new instance of the element is created and then the events that affect that instance are replayed one after the other in the right order to put the element into the correct state.

you could keep instances of your domain objects around and subscribing to new events so that they can be kept up to date without loading them from all the events every time, but usually its quick enough just to load all the events from the database and apply them every time in the same way that you might load the instance from the database on every call to your web service.

*Unless you have snapshots of you domain object to reduce the number of events you need to load/process

like image 26
Sam Holder Avatar answered Jan 10 '23 15:01

Sam Holder