Conflict Resolution
One of the major advantages of being explicit about the meaning of changes, is that you can detect conflicting changes with more precision. Typically, these conflicting changes occur when two users are acting on the same data (nearly) simultaneously. Imagine two users, both looking at a specific version of the data. They both decide to make a change to that data. They will both send a command like "on version X of this aggregate, do that", where X is the expected version of the aggregate. One of them will have the changes actually applied to the expected version. The other user won’t.
Instead of simply rejecting all incoming commands when aggregates have been modified by another process, you could check whether the user’s intent conflicts with any unseen changes.
To detect conflict, pass a parameter of type ConflictResolver
to the @CommandHandler
method of your aggregate.
This interface provides detectConflicts
methods that allow you to define the types of events that are considered a conflict when executing that specific type of command.
Expected Aggregate Version
The |
If events matching the predicate are found, an exception is thrown (the optional second parameter of detectConflicts
allows you to define the exception to throw).
If none are found, processing continues as normal.
If no invocations to detectConflicts
are made, and there are potentially conflicting events, the @CommandHandler
will fail.
This may be the case when an expected version is provided, but no ConflictResolver
is available in the parameters of the @CommandHandler
method.