0

I have a CQRS application with eventual consistency between the event store and the read model. In it I have a list of items and under the list a "Create new" button. When a user successfully creates a new item he is directed back to the list but since the read model has not been updated yet (eventual consistency) the item is missing in the list.

I want to fake the entry in the list until the read model has been updated. How do I best do that and how do I remove it when the new item is present in the actual list? I expect delays of about 60 seconds for the read model to catch up.

I do realize that there are simpler ways to achieve this behavior without CQRS but the rest of the application really benefits from CQRS.

If it matters the application is a c# mvc4 application. I've been thinking of solutions involving HTML5 Web Storage but want to know what the best practice is for solving this kind of problem.

Johan Gov
  • 1,262
  • 1
  • 13
  • 26

3 Answers3

1

It doesn't matter that's a asp.net mvc app. The only solution I see, besides just telling the user to wait a bit, is to have another but this time synchronous event handler that generate the same model (of course the actual model generation should be encapsulated in a service) and sends it to a memory cache.

Being everything in memory makes it very fast and being synchronous means it's automatically executed before the request ends. I'm assuming the command is executed syncronously too.

Then in your query repository you also consider results from cache, removing it if that result is already returned by the db.

Personally, for things that I know I want to be available to the user and where the read model generation is trivial, I would use only synchronous event handlers. The user doesn't mind waiting a few seconds when submitting something and if updating a read model takes a few seconds, you know you have a backend problem.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
1

In this situation, you can present the result in the UI with total confidence. There is no difference in presenting this information directly and reading it from the read model.

Your domain objects are up to date with the UI and that's what really matters here. Moreover, if you valid correctly your AR state in every operation and you keep track of the concurrency with the AR's version then you're safe and your model will be protected against invalid operations.

At the end, what are the probability of your UI going out of sync? This can happen if you there are many users modifying the information you're displaying at the same time. This can be avoided by creating task based UI and following the rule 'one command/operation in the AR per request'.

The read model can be unsynced until the denormalizers do their job.

In the other hand, if the command will generate a conversation (long running operation) between a saga and AR's then you cannot do this and must warn the user about it.

Alex Pollan
  • 863
  • 5
  • 13
  • Thank you for your answer @Alex. This is the pretty much the conclusion me and my team has come to too. Does the AR abbreviation stand for Aggregate? – Johan Gov Nov 05 '13 at 07:22
  • Yes, Aggregate Root (includes its entites)... by the way, which framework do you use (if you use one) "to do" CQRS? – Alex Pollan Nov 05 '13 at 08:40
  • In addition to what we have said here,...The main point here is that the risk you asume in the UI is low, and in some cases allowed, in comparison to the gain that you get with CQRS. Keep in mind also that, in some cases, this way of thinking won't free you off the responsibility of refine the UI to improve the responsiveness. – Alex Pollan Nov 05 '13 at 08:54
0

I see that eventual consistency is applicable to application only if application environment has multiple front-end servers hosting application and all these servers has own copy of read model. All servers uses same copy of event store.

When something is changed to event store, read model that is used to read result to user must be updated in sync with event store. Rest of servers and read models managed by them can be updated using eventual consistency.

This way result to user (list of items) can be read from local read model copy because it is already updated in sync. No need for special complex fake updates/rollbacks.

Only case when user can see incomplete list is that user hits F5 to refresh list after update change and load balancing directs user request to front-end server which read model is not yet updated (60 second delay), but this can be avoided so that load balancing does not change users server in middle of session.

So, if application has only one front-end server, eventual consistency is not very usable or it does not give any benefits without some special fake updates/rollbacks with read model...

Harza
  • 111
  • 1
  • 11
  • I disagree with that. Eventual consistency has nothing to do with the number of servers or if the app is distributed or not. Once you have 2 related models that are unsync'd but that will be sync'd in the future, you have eventual consistency. CQRS provides great flexibility for any app (big, small, local or distributed) but the trade off is having to deal with message driven architecture quirks: service bus, idempotency and eventual consistency. – MikeSW Oct 23 '13 at 07:41
  • Yep you are right. My point was more that when data is needed to read, that data should be updated in sync, somehow. I don't recommend fake updates because they add unnecessary odd complexity to the system. – Harza Oct 24 '13 at 09:58