Preventing Duplicate Aggregates

What is the best way to prevent duplicate aggregates?
Should it be done by the application before sending to commandbus?
By the aggregate root itself?
By the eventstore?
The eventstore is the easiest since it is usually backed a persistent store.
But it’s too late in the processing path.
I need to prevent duplicate aggregate root from being created in the first place.

The application should do it before sending a command. It’s a pretty easy (and cheap) query to perform.
The event store does it anyway, so if the app fails to do it, the store will.

Cheers,

Allard

Can you please point me to where and how the eventstore is checking for duplicates?

The EventStore only has teh appendEvents() and readEvents() methods defined.
I supposed I can call readEvents() and if it returns anything then that means there is a duplicated.
However readEvents() may be too expensive to call since it may actually return all the events, and not just check for duplicate.
Maybe we need to add a checkID() call to EventStore?

Hi Ming,

maybe I was a bit too generic. The JPAEventStore and MongoEventStore use unique keys to make sure that there is at most one event for each aggregate with the same sequence number. This will ensure that you can never create two aggregates with the same identifier (as they’ll both have an event with sequence number 0).

Cheers,

Allard

Hi Allard,

I use Axon 2.0, MongoEventStore and my Aggregate Identifier is a String.

I am still able to create two aggregates with the same identifier.

Are you sure that this should not happen?

Thanks
Hannes

Hi Hannes,

the MongoEventStore relies on Mongo to detect key violations. The enuseIndexes method (which is annotated with @PostConstruct) creates the neceassary indexes if they don’t already exist.

The unique key in the event store (by default) is the combination of the aggregate type, aggregate identifier and sequence number fields. That means you can still have two of the same aggregate identifiers, as long the aggregates have a different type.

Hope this helps.
Cheers,

Allard

Hi Allard,

strange, because I am able to create two aggregates with the same identifier and the same aggregate type. The sequenceNumber for both is 0.

Hmm…

Hannes

I added a little test case to Axon to make sure this really works as expected.

Which version of MongoDB are you using? Did you check that the indexes are properly set?

fyi

For my application I ended up using a Interceptor.
My “unique” Interceptor checks the id first against a bloomfilter.
If bloomfilter comes back with a potential match then it checks against my (Cassandra)eventstore.