Eventual consistency - Conflict resolver

Hi,

I’m working on a PoC to evaluate the use of Axon framework for the development of a new application.

Note: I find the documentation well written but in some cases are missing code examples to help you better understand the implementation process (also on github I didn’t find much). Is there a project that implements complex scenario?

My concern is about the eventual consistency with the CQRS pattern. Consistency is a requirement for us.

There are a lot of articles and threads about this topic, so I apologize if I’m creating a duplicate thread.

Axon offer a conflict resolver but I’m not sure to understand how it works.
I found an example on a open source project.
This solution stores the version of the aggregate in the event store and read model. The client will read then the version from the read model.
What if I have different read models, could there be version conflicts?
How does Axon solve the conflicts?

Thanks

Hi Pietro,

I think you may be mixing two different consistency concepts here. One is the consistency of the aggregate (will a state changing operation be operating on actual or obsolete data) and the other is consistency between the read and write models.

The conflict resolver you mentioned is meant to help you with the former but not the later. I’m not an expert in the subject and perhaps @Steven_van_Beelen and/or @allardbz will correct me here and/or provide more details but I’ll try to briefly explain the purpose of the conflict resolver to the best of my knowledge.

When one sends a command that contains @TargetAggregateVersion to an aggregate, the expectation is that the command handler would update the state of the aggregate from what it was at that particular version. The version information is crucial if the command handler relies on calculations and/or reasoning that involves both the aggregate’s state (at given version) and the command’s payload.

Because of the async nature of command handling, chances are other commands may have changed the state of the aggregate in the time frame between when this client sent the command and the time command handler started processing it. Those changes may have been applied to the very same data the current command will modify (which means it should be rejected) or on totally unrelated part of the aggregate’s data (which means it can proceed). The conflict resolver you mentioned is meant to tell the command handler if there is a conflict or not.

For example in the open source project you linked to, the command handler uses a conflict resolver that basically says “Reject the command if any of the DepositedEvent, WithdrawnEvent, MoneySentEvent, MoneyReceivedEvent events have occurred since the version I expect (as they cause conflicts). Otherwise proceed”. A much simpler and perhaps easier to understand example is the framework’s ConflictResolutionIntegrationTest.

I hope that helps understand the role of the conflict resolver. As for the

My concern is about the eventual consistency with the CQRS pattern

I’m afraid I can’t help much with that. The way I understand it, eventual constancy is at the heart of CQRS. Obviously you can have various ways of marking and tracking data as it flows through different systems. That said, I don’t think you’ll ever be able to have the type of consistency RDBMS provide.

1 Like

Hi Milen,

Thanks for the clear and detailed explanation.
I was thinking the conflict resolver was something like git auto merge.

Expected behaviour example
If the command handler receives an old version, but the changes on the aggregate are on different fields compared to the latest version, then the resolver would increase the version number and allow to save the event.

So the conflict resolver only helps for conflict detection, did I understood right?

Thanks

So the conflict resolver only helps for conflict detection, did I understood right?

Essentially yes.

You can have a look at the DefaultConflictResolver to see how it gets all the “unexpected” events and matches them against a predicate that you provide. If anything matches it’ll throw an exception (that you can also provide).

You can also have a look at Conflicts which (as its JavaDoc states) is a

Utility class providing common Predicates used to detect conflicts between the actual state of an event sourced aggregate and the expected state of the aggregate.

1 Like

I must agree with you @gpietro, there’s much to gain on documentation and samples.
We know this and are working on it. Things are moving along luckily, but I understand it could be cumbersome for you, right now. That’s where this forum shines I think; you can ask about whatever topic you run into with Axon.

Additionally, there is another sample out there, constructed by a former colleague of ours (read: AxonIQ). It explains roughly the same thing @milendyankov already pointed out, but figured it might still be valuable. You can find it here by the way.

1 Like