Reputation: 876
I have two aggregates with the same identifier. I know it might sound weird, but the reason why I want to do this is because BaseAggregate has too many features and I want to separate codebase so it's still be able to maintenance and also be able to scale. So developers on FooAggregate can focus on their own features while shared some state that may need from the developers on BarAggregate. Here's the problem when dispatching commands to FooAggregate and BarAggregate at the same time it's conflict with aggregateSequenceNumber on the event store. So I do a lot of research and found that aggregate is locked whenever there's a command being executed, but these 2 aggregates deploy on the different JVM so It would not prevent each other from executing a command. I want it to be done on the command bus instead. So let's say FooCommand and BarCommand (with the same identifier) were dispatched at the same time. I want the command bus to wait until either FooCommand or BarCommand succeeded then execute the next command. Is there a way to config command bus to behave like this and would it affects the performance?
abstract class BaseAggregate {
@AggregateIdentifier
public String identifier;
// I use event-sourced approach so this state can be build up from events (with the same identifier)
// and share among other services
public List<String> sharedState;
}
class FooAggregate extends BaseAggregate {
public void handle(FooCommand command) {
// apply event
}
}
class BarAggregate extends BaseAggregate {
public void handle(BarCommand command) {
// apply event
}
}
Upvotes: 0
Views: 605
Reputation: 7275
Before moving to your exact question, let me focus on the following:
So developers on FooAggregate can focus on their own features while shared some state that may need from the developers on BarAggregate.
You should not read the state from one aggregate instance into another. The aggregate instances are isolated units that perform validation on their own state. If the consistency boundary should be broadened to include more entities within your system, that means you have a larger aggregate scope.
Having said that, I am guessing you might have worded your question a bit off. I am basing this on the fact you're using a polymorphic aggregate, which is a fine way to model your domain. What's not clear from your issue description nor the code, is whether you're configuring this correctly.
If you're using Spring, you can place Axon's @Aggregate
annotation on the parent class. In your case, that's the BaseAggregate
. That'll correctly tell Axon Framework it's dealing with a polymorphic aggregate.
If you're not using Spring, you will have to use the AggregateConfigurer
like so:
AggregateConfigurer<BaseAggregate> configurer =
AggregateConfigurer.defaultConfiguration(BaseAggregate.class)
.withSubtype(FooAggregate.class)
.withSubtype(BarAggregate.class);
With that said, we can move onwards to what you're actually asking.
Whether the CommandBus
can lock the aggregate for you.
Axon Framework's locking scheme works on the Repository
.
More specifically, there's a LockingRepository
class that's implemented by any Repository
within Axon Framework.
This component ensures that anytime an Aggregate is loaded, it'll be locked, ensuring duplicate access cannot occur.
However, the lock is intently not a distributed lock, as this generates an entire scheme of others problems on its own. Thus for simplicity, that's were it resides.
Knowing this, it's not the job for a Command Bus to lock, but for a Command Bus to ensure commands for the same aggregate are routed consistently. That's actually what Axon Frameworks distributed Command Buses do!
If you'd use Axon Server, that behavior would be seamless. Note that this works with both the Standard (free) and Enterprise editions of Axon Server. You can even go for AxonIQ Cloud if you will.
If you're not using Axon Server, you will have to set up a distributed command bus yourself. This can be done with either Axon's Spring Cloud or JGroups Extension.
Upvotes: 2