How to handle set based consistency validation in CQRS?
I have a fairly simple domain model involving a list of Facility
aggregate roots. Given that I'm using CQRS and an event-bus to handle events raised from the domain, how could you handle validation on sets? For example, say I have the following requirement:
-
Facility
's must have a unique name.
Since I'm using an eventually consistent database on the query side, the data in it is not guaranteed to be accurate at the time the event processesor processes the event.
For example, a FacilityCreatedEvent
is in the query database event processing queue waiting to be processed and written into the database. A new CreateFacilityCommand
is sent to the domain to be processed. The domain services query the read database to see if there are any other Facility
's registered already with that name, but returns false because the CreateNewFacilityEvent
has not yet been processed and written to the store. The new CreateFacilityCommand
will now succeed and throw up another FacilityCreatedEvent
which would blow up when the event processor tries to write it into the database and finds that another Facility
already exists with that name.
The solution I went with was to add a System
aggregate root that could maintain a list of the current Facility
names. When creating a new Facility
, I use the System
aggregate (only one System
as a global object / singleton) as a factory for it. If the given facility name already exists, then it will throw a validation error.
This keeps the validation constraints within the domain and does not rely on the eventually consistent query store.
Three approaches are outlined in Eventual Consistency and Set Validation:
- If the problem is rare or not important, deal with it administratively, possibly by sending a notification to an admin.
- Dispatch a DuplicateFacilityNameDetected event, which could kick off an automated resolution process.
- Maintain a Service that knows about used Facility names, maybe by listening to domain events and maintaining a persistent list of names. Before creating any new Facility, check with this service first.
Also see this related question: Uniqueness validation when using CQRS and Event sourcing