Come gestire la convalida della coerenza basata su set in CQRS?

Ho un modello di dominio abbastanza semplice che coinvolge un elenco di radici aggregate di Facility . Dato che sto utilizzando CQRS e un event-bus per gestire gli eventi generati dal dominio, come potresti gestire la convalida sui set? Ad esempio, supponiamo di avere il seguente requisito:

  1. Facility devono avere un nome univoco.

Dal momento che sto usando un database alla fine coerente sul lato della query, non è garantito che i dati in esso contenuti siano accurati nel momento in cui i processi degli eventi o elaborano l’evento.

Ad esempio, FacilityCreatedEvent trova nella coda di elaborazione degli eventi del database delle query in attesa di essere elaborata e scritta nel database. Un nuovo CreateFacilityCommand viene inviato al dominio da elaborare. I servizi di dominio interrogano il database letto per vedere se ci sono altre Facility già registrate con quel nome, ma restituisce false perché CreateNewFacilityEvent non è ancora stato elaborato e scritto nell’archivio. Il nuovo CreateFacilityCommand ora riuscirà e genererà un altro FacilityCreatedEvent che esploderà quando il processore degli eventi prova a scriverlo nel database e scopre che esiste già un’altra Facility con quel nome.

La soluzione che ho seguito è stata l’aggiunta di una radice aggregata di System grado di gestire un elenco dei nomi di Facility correnti. Quando creo una nuova Facility , utilizzo l’aggregazione di System (solo un System come object / singleton globale) come fabbrica per esso. Se il nome della struttura fornita esiste già, verrà generato un errore di convalida.

Ciò mantiene i vincoli di convalida all’interno del dominio e non si basa sull’archivio di query alla fine coerente.

Tre approcci sono delineati in Eventual Consistency e Set Validation :

  1. Se il problema è raro o non importante, gestirlo in modo amministrativo, eventualmente inviando una notifica a un amministratore.
  2. Invio di un evento DuplicateFacilityNameDetected, che potrebbe avviare una procedura di risoluzione automatica.
  3. Mantenere un servizio che conosce i nomi delle strutture utilizzate, magari ascoltando gli eventi del dominio e mantenendo un elenco persistente di nomi. Prima di creare qualsiasi nuovo impianto, verificare prima con questo servizio.

Vedi anche questa domanda correlata: convalida di unicità quando si utilizza CQRS e il sourcing di eventi

In questo caso, puoi implementare un semplice servizio di stile CRUD che fondamentalmente fa un inserimento in una tabella Sql con un vincolo di chiave primaria.

L’inserimento avverrà solo una volta. Quando i comandi duplicati con lo stesso valore che dovrebbero esistere solo una volta colpisce l’aggregato, l’aggregato chiama il servizio, il servizio non riesce l’operazione di inserimento a causa di una violazione del vincolo della chiave primaria, genera un errore, l’intero processo non riesce e nessun evento vengono generati, non vengono riportati report nel lato query, è ansible segnalare l’errore in una tabella per il controllo di coerenza finale in cui l’utente può eseguire query per conoscere lo stato dell’elaborazione del comando. Per verificarlo, basta interrogare ancora e ancora il Command Status View Model con Command Guid.

Ovviamente, quando il comando contiene un valore che non esiste nella tabella per il controllo della chiave primaria, l’operazione è un successo.

La tabella del vincolo di chiave primaria deve essere utilizzata solo come servizio, ma, poiché è stato implementato il sourcing di eventi, è ansible riprodurre gli eventi per ribuild la tabella del vincolo di chiave primaria.

Poiché il controllo dell’unicità verrà eseguito prima della scrittura dei dati, il metodo migliore consiste nel creare un servizio di tracciamento degli eventi, che invierebbe una notifica quando il processo è terminato o terminato.