Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing changes in View when using CQRS & DDD with Domain Events & ServiceBus

I'm a little confused about the flow in a system using domain events to build the read model. Particularly, how do we deal with the fact that the user expects data (and its view) to change when they complete a command, but due to our system architecture (non-blocking calls to publish events) the actual database might not change before the page is reloaded?

I'm hoping to move the design of one of our systems more inline with CQRS using events and a service bus.

Let's say my flow goes as such:

  1. User clicks button in View to perform Task of removing Payment Method from their Account.

  2. Controller calls PaymentMethodRemovalService, passing it accountId & paymentMethodId.

  3. Controller uses AccountRepository to retrieve Account and calls account.RemovePaymentMethod(id)

  4. Account validates that operation can occur and publishes event PaymentMethodRemovedMessage(accountId, paymentMethodId)

  5. Because event publishing is asynchronous, we now have to return from service and return view from the controller - but our actual data isn't updated yet!

  6. A handler, IHandle< PaymentMethodRemovedMessage >, hears the event and removes the actual row from the DB

So, what's a guy to do?

I could simply, say, remove the div that was displaying the payment method. This may work in an AJAX scenario, but what if I'm using Post-Redirect-Get to support non-JavaScript clients. Then I will be firing my Get and reading the data from the Query side of things, potentially before it's updated.

Do I just show a notification saying their request to remove the payment method has been submitted? (which doesn't seem to friendly, makes sense for submitting an order, but not for, say, changing an address).

Is there a way to reconcile implementing changes as decoupled asynchronous events and showing the user data that reflects their current change?

EDIT: My question is quite similar to CQRS, DDD synching reporting database I have to say, the answer given there and also alluded to here, has a bit of a smell to it - wrangling the UI to show an update that's out of band with the read DB, so to speak. I was hoping for something a little cleaner.

like image 758
quentin-starin Avatar asked Oct 06 '10 17:10

quentin-starin


People also ask

What is the difference between CQRS and event sourcing?

CQRS is implemented by a separation of responsibilities between commands and queries, and event sourcing is implemented by using the sequence of events to track changes in data.

What problem does CQRS solve?

CQRS allows you to define commands with enough granularity to minimize merge conflicts at the domain level (any conflicts that do arise can be merged by the command), even when updating what appears to be the same type of data.

How does CQRS pattern work?

CQRS separates reads and writes into different models, using commands to update data, and queries to read data. Commands should be task-based, rather than data centric. ("Book hotel room", not "set ReservationStatus to Reserved").

What is read model in CQRS?

Read Models are about Queries This is where read models come in. A read model is a model specialized for reads, that is, queries. It takes events produced by the domain and uses them to build and maintain a model that is suitable for answering the client's queries.


1 Answers

If you are locked into the Request/Response model you could adopt a Correlated Request/Response pattern. For specifics, check out the Async Pages sample in the NSB download. This demonstrates Request/Response in an ASP.NET setting. There are some ASP.NET MVC examples out there if that is more your thing.

When you introduce asynchronous processing you are accepting that the data will be stale. One can argue that the moment you query the DB the data is already old(network latency, rendering time etc.). Since the data is already old, we must ask how old is good enough?

One more thing to consider is that your processing is a bit out of order. Step 3 should be validating the command prior to sending it to the server and then steps 3, 4 would come after 6. The database should only be updated if the command is valid and the event should only be published if the database is successfully updated.

like image 153
Adam Fyles Avatar answered Sep 22 '22 13:09

Adam Fyles