'Command Side Projections' for uniqueness constraints

There is a common situation that at the point of the creation of an aggregate we need to do a uniqueness check.

For example for the creation of a User aggregate we want email fields to be unique across all aggregates (example taken from [1]).

I believe that this problem is a general instance of the larger ‘Set Validation’ problem mentioned in [2]. To resolve the problem we would need “to validate the uniqueness against an immediately consistent datastore” (e.g. database table with unique constraint on the email column) before dispatching the command [2].

There are many ways to implement this within Axon:

  • In [3], Steven Grimm describes “the old-fashioned way” of placing a a constraint on a SQL
    table in the query model.
  • Working with a distributed lock would also work. I think [4] is a good video explaining how to
    do this in Spring.
  • In [5] @allardbz lists techniques you could use including using a 2 step process with a Saga.
  • In [6] @Sebastian_Ganslandt1 suggests using “an interceptor that checks the incoming create-commands against this query-model and rejects the command if it contains a duplicate”.
  • @Ivan_Dugalic in his answer in [1] wrote that you can also use ‘command side projections’.

If I was trying to solve this using a Saga then could I create a Saga which has @StartSaga on a @CommandHandler rather than an @EventHandler? The saga would then send further commands until finally the last @CommandHandler (annotated with @EndSaga) either creates the User or does not. Using a saga with events does not feel right for this purpose (but using commands seems to make more semantic sense to me).

Or if trying to solve this using ‘command side projections’ how exactly does that work?

  • Do we essentially just create a @Component which has a @CommandHandler that as part of
    its logic takes some sort of lock and validates the constraint?
  • How exactly would you implement this?

Are there any code examples illustrating this ‘set validation’ pattern using command side
projections in Axon that I could use to understand?

Regards,
vab2048

[1] Route one command to multiple aggregates
[2] Validating Uniqueness
[3] Validating Uniqueness
[4] https://www.youtube.com/watch?v=firwCHbC7-c
[5] How can I prevent Asynchronous EventHandler handles events that should be rollbacked
[6] Best appoach to pre creation bus rules for aggregate

1 Like

Hi vab2048,

We get this question often and I am working on a blog about this topic which will be published soon. This blog elaborates more on the answer that @Ivan_Dugalic gave. To give you a sneak preview this is a link to code samples that I use for this blog Set based consistency validation with Axon.
I’ll let you know when the blog has been published.

Kind regards,

Yvonne

5 Likes

Hey vab2048,

In addition to her blog, Yvonne will be talking about set based validation in a podcast with me that will be released soon. We’ll keep you posted. :slight_smile:

3 Likes

Hello vab2048,

The blog has been published and you can find it here

2 Likes

Hi,

How will the look-up table solution scale, if we’re using multiple instances of the commands processors?

Thanks,
Eliezer

Hi Eliezer,

You can only have one command handler for a command. Are you in a situation where you need this lookup table for a lot of commands or do you have an example?
Because all rows of the table need to be available (for complete validation) you 'll need to keep the number of columns in this table as low as possible and add indices on the search columns.

Yvonne

Hi Yvonne,
I presume that in a scalable solution, multiple instances of the same command handler can be deployed.
In this scenario, should we use a dedicated lookup table for each instance, or should we use a central one?
Thanks,
Eliezer

Hi Eliezer,

This should be a central lookup table to be able to validate the whole set.

Yvonne

Hi Yvonne,

I’m wondering if this approach also takes concurrency into the account? For example, if 2 commands intending to create the accounts with the same email address arrive at the same time, there’s a chance that both of these commands will pass through the Dispatcher Interceptor validator and when they reach the command handler, 2 AccountCreatedEvents will be raised. One of them will obviously fail to update the lookup table due to a unique constraint violation, but still, I have 2 questions:

  • will this failure cause to “roll back” the even from the EventStore? In other words, is this Subscribing Event Processor executed in the same UnitOfWork that the command that originally raised the event?
  • even if the lookup table and even store updates participate in the same UnitOfWork, they are still done against different storages. Isn’t this sort of a distributed transactions problem then (which again, can not guarantee the immediate consistency)?

Kind regards,
Beka