Read side implementation approaches using CQRS

2019-03-09 03:04发布

问题:

I've moved to the project which is actively using CQRS + event sourcing. From the first glance it's implemented in accordance with all those books and blogs, but finally I realized what exactly is peevish in the implementation.

Here is CQRS architecture:

Originally I took this picture from here.

As we can see in the picture, the read side receives events from the queue and passes it one by one into different sets of projections(denormalizers) and then resulting ViewModels are saved through AddOrUpdate method into, say, DB. So as I understand from the picture denormalizer can rely only on the event itself plus data from read-side db. For instance:

  1. Account view already stored in the db.
  2. EmailChanged event arrives
  3. We read Account view from the DB
  4. Applying Email change to it
  5. We save Account back into DB.

Another case(counting number of some items, say orders):

  1. OrderCreated event arrives
  2. We read the ViewModel which represents NumberOf previously arrived orders
  3. Increment and save this.

What we have in our project: We use all those events only as a notifier that something changed in the domain model. Hence, what we do:

  1. We take domain repository and read all the necessary aggregates. Doing so we get the most recent state of them.
  2. We just build the ViewModel object from scratch
  3. Save newly created object into Db

The approach we use in our project looks a bit strange to me, I can't see all the drawbacks of it though. If we need to rebuild our read side, we add "active" denormalizer and next time it receives a particular event, it recreates the new viewmodel.

If we use approach from the books, I will have to have a separate utils logic somewhere out of my system for rebuilding. What we need for this:

  1. Drop the read side
  2. Read all the events from the event store from the beginning
  3. Pass them through the projections

So my question is:
What is the right approach in here?

回答1:

The approach we use in our project looks a bit strange to me, I can't see all the drawbacks of it though.

One prominent drawback is that upon receipt of the event, you have to make an additional call to the repository of the corresponding aggregate. This means that this repository must be exposed, either directly or as a service. In addition to increased dependencies is the additional IO.

For rebuilding from an event store, the approach you describe is the generally accepted method. An approach described here makes use of an event log dedicated for rebuilding projections. This can be used to address performance issues while rebuilding. Also take a look at Scalable and Simple CQRS Views in the Cloud and on DDD/CQRS mailing list.