How to version commands?

Hello,

I have a question about when and how properly to put version of aggregate inside command that is designed for it.

I think that the following example should show what I’m interested in.

Consider an EventSourced aggregate:

`

class Wallet {
lateinit var id: WalletId

var availableCoins = 0

fun handle(cmd: AddCoins) {
apply(addedEvent)
}

fun handle(cmd: RemoveCoins) {
apply(removedEvt)
}

//… basic creation things, event sourcing handlers etc

}

`

In the distributed scenario, let’s suppose that i cannot prove synchronous operation based on the command bus of axon server, at some point there might be situation where RemoveCoins could be executed twice at the same time using the same aggregate version which would end up creating race condition.

The question is, how do i ensure in distributed scenario that the command handler will be handled on the latest version, meaning before handling the command i can provide it current aggregate version, so at the point in time of dispatching until handling the version should not change if this command is meant to be handled. How do i load current aggregate version without listening to every event that it publishes? Is there an easy way around it?

Hi Robert,

Firstly I’d like to point out that Axon Server does not use the DisruptorCommandBus internally.
All that the Axon Server Command Bus does is provide a traversal means to get your Command Message from one instance to another, in a similar fashion as the DistributedCommandBus does.
Once a Command Message arrives at a client application, like the Wallet-Application sample you provided, that’s when it’ll be transferred from the Axon Server Command Bus over to the Local Command Bus (this is what we call the ‘local segment’).
What implementation of Local Command Bus is used is entirely up to you.
By default, this would be the SimpleCommandBus.

You could decide to change this over to the DisruptorCommandBus if necessary.

Now, for the actual question at hand.
To ensure versioning between Aggregates and commands, you can utilized the @AggregateVersion annotation (to be placed on your Aggregate implementation) and the @TargetAggregateVersion annotation on your command message.
This should ensure that a given command will be executed on the right version of an Aggregate.

However, after reading your question a couple of times, I am not entirely sure whether the suggested approach is what you’re looking for.
What do you actually mean with Aggregate Version?
An implementation version? Or the state of a given Aggregate after handling a set of events?

In case of the implementation-version, I’d follow the suggestion I gave earlier.
If it’s to ensure that an oddly timed second occurrence of the same RemoveCoins command will not be dealt with, then I’d opt for introducing state in the command message at hand to be used to make this decision.
Something like the balance to be expected of the wallet when the RemoveCoins command is dispatched.
That way, if by chance a second instance of the same RemoveCoins command is dispatched and handled, then your command handler can decide against executing it because the wallet-balance in the second instance does no correspond with the actual balance of the Wallet Aggregate.

Concluding, I hope this helps you out Robert!

Cheers,
Steven

Hey Steven,

Thank you so much!
Few days ago i realized that the disruptor is per service not on the AxonServer, so your answer clarified that even more.

Regarding the versioning, yes, I was referring to the second occurrence so your answer also clarified that, and well i’ve been storing the transactions in the aggregate and checking if the transaction was processed before, the ‘expected balance’ inside command handler approach could be tricky since there might be transactions with the same balance when there are alot of transaction on this aggregate, so i think i got that part properly.

The interesting part is where you mention the implementation version of aggregate, are you saying that i could have multiple classes implementing aggregate, what do you have in mind by the implementation?

I thought the aggregate version refers directly to the sequence number of the last event of that aggregate, this is why i first thought that could ensure that there were no events applied before the RemoveCoins command

Hi Robert,

I was put on track of the @AggregateVersion annotation because you were talking about the Aggregate Version.
Honestly, I don’t think you need it at this stage.
The idea behind the annotation is that you could do a rolling deployment of your application, where your a given Aggregate has changed significantly between deployments.
The rolling deployment means that at the same time you have old implementations and new implementations of a given Aggregate in existence.
Thus, you will likely need to ensure that the old application dispatches commands tied to the old Aggregate Version, whilst the new implementation uses a new Aggregate Version.

So again, I don’t think you should be bothered about the specifics of Aggregate Versioning at this stage. :slight_smile:

Happy to hear the rest of my reply clarified some concepts for you!

Cheers,
Steven