Oddleif
Oddleif

Reputation: 791

CQRS How to get aggregates final version?

Say you have a command that potentially can generates multiple events on an aggregate. How do you figure out what the final version actually is? So you don't get it from the read model until you know all events are processed.

ServiceLocator.CommandBus.Send(new SomeCommand(..., currentVersion));

Using a command bus I see no obvious ways of getting a return value stating the new aggregate version.

Suggestions?

Upvotes: 1

Views: 450

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57229

As far as I can tell

  1. You are on exactly the right track
  2. Yup, the command bus is getting in your way

Since the command bus isn't allowing you to pass back the information that you want, you'll have to pass it forward, then query it. The command handler writes the information you want somewhere, and you query it after getting the signal that the command has completed.

In other words, you can think about the application itself as an abstraction where you send it commands, the commands update version numbers, and you query those version numbers. This abstraction has been split into separate responsibilities -- the command responsibility is implemented via the command bus, and the query responsibility by... well, that's the bit to work out.

Each of your command messages should have a unique identifier (you are going to want something like for idempotency anyway). After the events are successfully persisted, the command handler writes the new version number in to key-value store, using the command id as the key.

In your caller, you block until that entry is available; then read it from the store and move on.

Not my favorite choice, but it doesn't really violate any of the principles of good/successful design that we have been taught.

For instance, Gregor Hohpe talks about using a correlation identifier to coordinate between request messages and reply messages. In this example, the request would be the Command, with it's identifier, and the reply would be an message that describes the new high water mark of the stream.

You might imagine, for instance, that the application gets the list of new events for your event sourced entity, saves them, then publishes a new event saying "the stream is now at version 12345". Your code, having submitted the command message, just blocks until the high water message arrives.

(If the message doesn't appear in a reasonable amount of time? Resend the command! We make sure that commands are idempotent so that will be an option.)

Another possibility: maybe you don't really need to know the high water mark at all; after all, you have the command id. If the events persisted by the command have a causation identifier (meaning, each event is tagged with the id of the command that produced it), and you trust that the event history is saved atomically, then... keep the query separate from the command; when the command is finished, "redirect" to the query, passing along the command identifier, and have the query block until at least one message with the right command id appears in the history.

Honestly, this is the same behavior as before, just putting the blocking in a different place.

Another possibility is that the client keeps track of the version itself. Rough idea is that even though the book of record is protected by the server, the client can have its own copy of the model, and a cache of the objects that it cares about. The client runs the command locally to ensure that it won't foul anything, then sends the command to the server -- already knowing what the answer is going to be if the command is successful.

Think of it as another form of optimistic concurrency.

Upvotes: 1

Related Questions