J. La
J. La

Reputation: 3

Event sourcing, Eventually Consistent, CQRS

I am currently stuck in a problem and hope you can help me with some ideas or best practices here...

Let's say I have an application using Event Sourcing and CQRS. I have

The current state of my application is

I have a Calculation service that subscribes to Red Pot service, Green Pot service and Settings service. I have a View Updater service that additionally subscribes to the Calculation service and updates the read model on any changes.

Now the following events are dropping in:

  1. Green Pot: 25
  2. Setting: Green Pot

The View Updater service is a bit busy today and has some delay in updating the view model.

The Calculation service handles the Green Pot event. It fetches the setting from read model (which is still set to Red) and does nothing.

After that the Calculation service handles Settings event. It fetches the Green value (which is still 20) from read read model and sends a new event (Result: 20)

After that the View Updater handles both events and updates the read model.

In this case, my application is not consistent - not even eventually.

Do have any thoughts how to handle something like this? Thanks for any ideas :-)

Upvotes: 0

Views: 463

Answers (2)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57397

First thought is that it isn't clear that you are sharing the common understanding of eventual consistency. Martin Kleppmann's talk emphasized three ideas

  • Eventual Delivery
  • Convergence
  • No data loss

Second thought is that you seem to have introduced a race condition into your Calculation service design. If RedPot, GreenPot, and Setting are separate aggregates/streams, then there really isn't any time binding between them. The arrival of events from those sources is inherently racy.

Udi Dahan wrote Race Conditions Don't Exist

A microsecond difference in timing shouldn’t make a difference to core business behaviors.

This is where convergence comes into play: you need to design your solutions so that they reach the same results even though the timing of messages is different. This often means that you need to include in your model some concept of a clock, or time, and some way of defining the interval in which some result is true.

As you've defined the problem, the Results produced by the calculation service are more about caching a snapshot than maintaining a history. So a different way to think about the problem you are having is to consider that the calculation service should not accept any arbitrary data from the read model, but rather one that aligns with the events that it is consuming.

Calculation service: "Hi, I can haz green pot as of event #40?"
Read model: "Sorry, no can haz, retry-after: 10 minutes"
Calculation service: "OK, I'll try again later."

Upvotes: 1

Constantin Galbenu
Constantin Galbenu

Reputation: 17713

The Calculation service should subscribe to and receive all events (GreenPotUpdated, RedPotUpdated and SettingsChanged).

It is not OK for the Calculation service to depend on an eventually consistent read-model. Instead it should maintain its own private state, ensuring that the events are received in the correct order.

Upvotes: 1

Related Questions