Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS: Update Read-Model without Event Sourcing

We have built a CQRS-based system using a relational DB on the domain-side and a NoSQL DB on the read-side. The domain-side follows a classical, relational approach while the read-side is denormalized. Data replication and transformation is done using events emitted by command handlers.

I have two questions regarding read-side synchronization:

  • What is the best way to completely rebuild the Read Model using the relational data on the domain-side?

    Let's assume the Read Model is out of sync. But even if it is always in sync, one may want to import a test database or do some bulk operations. So one may want to run the system from an existing write-model, without having the corresponding, synchronized read-model. As we do not use Event Sourcing, there is no way to replay all events.

    I currently consider a ReadModelBuilder which basically does a SELECT * FROM on each table and convert each entity to read-side representation. But this introduces redundancy. ReadModelBuilder would need to know how the transformation is done. So do the Event Handlers which normally do read-side synchronization after a Command Handler executed some write operations.

    I thought about discarding the Event Handlers and replace them with a synchronization mechanism on a per-class-level. E.g. instead of FooRenamedEventHandler renaming foo.name, it will call the FooReadModelBuilder which re-writes the complete Foo instance. But I think this has drawbacks. The FooRenamedEventHandler can deal much better with redundant usages of foo.name within the read-model.

    UPDATE: Another approach could be to let the ReadModelBuilder create read-model entities by segmenting the domain instance into events, which will build the complete read-side entity when executed sequentially. For example:

    Article domain entity has a Name and a Price. To build the read-side model, ReadModelBuilder could inspect the domain entity and emit ArticleCreatedEvent, ArticleRenamedEvent and ArticlePriceChangedEvent. That way, the transformation logic would stay within the event handlers but would still be callable from some kind of bulk replication mechanism.

    For example the ReadModelBuilders could look like this:

_

interface IReadModelBuilder<TEntity>
{
    //// Returns a sequence of events which replicate the read-model 
    //// when executed by the event handlers.
    Event[] GetReplicationSequence(TEntity instance);
}

END OF UPDATE

_

  • How do you generally detect a read model which is out of sync? Are there general best practices?
like image 549
mbnx Avatar asked Aug 30 '17 12:08

mbnx


1 Answers

If you don't persist the event (i.e. not using Event sourcing) then you can't easily rebuild a read-model. Your Rebuilder must somehow try to reverse engineer the write model and fabricate some events which is weird because the write model could not even contain all the information as it does not need it in order to do his job.

So, my conclusion is that, without an event store or at least an event log then you cannot rebuild your read-model. If you have some source of truth like this then you can rebuild it and even detect the out-of-sync situation by using a list of all processed event IDs in some persistence.

like image 154
Constantin Galbenu Avatar answered Oct 01 '22 02:10

Constantin Galbenu