Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a CQRS architecture with no explicit read model, which handler updates the data store?

This question has arisen out of a kind of existential crisis in an evolving architecture. Essentially it comes down to asking this - when the read model is the command model, should the command handler or the event handler update the data store?

Particularly I'm curious to know if there's an accepted way to approach this and if going down one route or the other could lead to well known problems.

To elaborate, we started with a domain model and some repositories to read from and update the data store via an ORM. These repositories query the existing domain model and we map results to DTOs - we didn't think about creating a separate read model at this point. The architecture has evolved to use the CQRS approach, so we're now issuing commands to create domain objects and events are being raised when commands are handled.

At this point we now have some fairly complicated model objects with all kinds of calculations going on and have (finally) realised that reads would be a lot faster if we persisted these calculations. So far so unexpected.

There is an idea to persist these calculations by adding fields to the current data store tables, thereby making our command model more like a read model. It has therefore been argued that we should be updating the data store in the event handlers because that's where the pattern says the read model should be modified.

i.e. if we issue a CreateItemCommand which is handled by a CreateItemCommandHandler which raises an ItemCreatedEvent, in turn handled by some ItemCreatedEventHandler, then the CreateItemCommandHandler should be reduced to merely validating the command and the actual modification of the data store should happen in the ItemCreatedEventHandler

The logic seems reasonable but it also seems to create a counterintuitive architecture. I thought the CQRS pattern required that a success event from a command handler indicate that something actually has changed in the domain model?

I can understand not wanting to update the read model in the command handler but not doing anything at all seems wrong, especially since we won't then be able to trust the ItemCreatedEvent to be telling the truth.

Is this ultimately subjective, or could there be other concrete reasons to go one way or the other?

like image 209
adhocgeek Avatar asked Mar 20 '23 14:03

adhocgeek


2 Answers

I think you may have better luck with a question like this on a CQRS forum, since this may require more of a back-and-forth discussion. Plus the real answer is probably "it depends".

That said, it sounds like you are mixing the "strict" definition of CQRS with more of the "accepted" definition of the pattern. The former is merely a separation of the read logic and write logic (and their structures). The latter is usually defined as having a highly denormalized read model and usually involves some form of event driven architecture (including event sourcing is some cases).

It sounds like you have something of a mix of these two ideas. My first question would be: what are your event handlers doing if they're not creating denormalized read models? Are they just notifying subscribers to invalidate cache and refetch data?

But bottom line, I think your instinct is correct--the event is published after the data has successfully been updated. If one handler's responsibility is to update the (command/write side) database, other subscribers have already been notified that this happened which may not be true if the update to the database fails.

So your command side should update the database, and your reads should be querying your normalized data store and projecting the results onto denormalized result sets. Again, events (if used at all) would probably just be used for notification that data has been updated, and that subscribers may need to requery (again, like cache invalidation).

like image 101
Phil Sandler Avatar answered Apr 06 '23 01:04

Phil Sandler


"This question has arisen out of a kind of existential crisis in an evolving architecture. Essentially it comes down to asking this - when the read model is the command model, should the command handler or the event handler update the data store?"

It does not really matter if the model is shared. In an ideal world you would have separated models, but as long as you keep the handler for events and commands separated you are grand, you wont of course benefit from database optimisations (reading/writing) but you have split the concerns. Don't forget that for now, you will be using the same model but what about the future? By keeping the handlers separated even though you are using the same model, it will make it easier for you to change to separated models. That layer should be hidden anyway, by using the repository patten. Commands are always the ones that ignite a change, never events; In a well structure domain you handle the event and fire another command.

UPDATE

Just to keep it clear you can off course change repositories in event handlers, but only for replicated data, data which does not belong to your service or data in the read models, i.e.:

Say you have two services, clients and warehouse, and within the clients service you have the clients details such as registration and address. According to SOA "rules" services should be independent, so if a new order is placed and the warehouse is requested to dispatch the item, it must have the address already, so again in a well structured domain, when client is registed, the clients' service publishes an event with the registration data, which might include the address, the warehouse service handles that events, extracts the address part of the event and persists it in its persistance layer.

So in this example events can perform a change in a repository but only for mirrored data. I thought it was important to make it a bit more explicit since I said in the comments bellow that events cannot start a change.

like image 37
MeTitus Avatar answered Apr 06 '23 01:04

MeTitus