Dato che non specifichi quale sarebbe lo scopo del database "write", assumerò qui che intendi questo: quando registri un nuovo aggiornamento in un aggregato, invece di ricostruire l'aggregato dall'archivio eventi, tu estrarlo dal database "write", convalidare la modifica ed emettere un evento.
Se questo è ciò che intendi, allora questa strategia creerà una condizione per l'incoerenza: se un nuovo aggiornamento si verifica prima che l'ultimo abbia avuto la possibilità di inserirlo nel database "write", il nuovo aggiornamento verrà convalidato rispetto a dati obsoleti, quindi potenzialmente emettendo un evento "impossibile" (cioè "non consentito") e corrompendo lo stato del sistema.
Ad esempio, considera un esempio permanente di prenotazione di posti in un teatro. Per evitare la doppia prenotazione, è necessario assicurarsi che il posto prenotato non sia già occupato: questo è ciò che si chiama "convalida". Per fare ciò, memorizzi un elenco di posti già prenotati nel database "write". Quindi, quando arriva una richiesta di prenotazione, controlli se il posto richiesto è nell'elenco e, in caso contrario, emetti un evento "prenotato", altrimenti rispondi con un messaggio di errore. Quindi si esegue un processo di proiezione, in cui si ascoltano gli eventi "prenotati" e si aggiungono i posti prenotati all'elenco nel database "write".
Normalmente, il sistema funzionerebbe in questo modo:
1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Projection process catches the event, adds seat #1 to the "already booked" list.
5. Another request to book seat #1.
6. Check in the list: the list contains seat #1
7. Respond with an error message.
Tuttavia, cosa succede se le richieste arrivano troppo rapidamente e il passaggio 5 si verifica prima del passaggio 4?
1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Another request to book seat #1.
5. Check in the list: the list is still empty.
6. Issue another "booked seat #1" event.
Ora hai due eventi per prenotare lo stesso posto. Lo stato del sistema è danneggiato.
Per evitare che ciò accada, non è mai necessario convalidare gli aggiornamenti rispetto a una proiezione. Per convalidare un aggiornamento, è necessario ricostruire l'aggregato dall'archivio eventi, quindi convalidare l'aggiornamento rispetto ad esso. Successivamente, si emette un evento, ma si utilizza la protezione data / ora per assicurarsi che non siano stati emessi nuovi eventi dall'ultima lettura dal negozio. Se fallisce, riprova.
La ricostruzione di aggregati dal negozio di eventi potrebbe comportare una penalità per le prestazioni. Per mitigarlo, puoi archiviare istantanee aggregate direttamente nel flusso di eventi, etichettate con ID dell'evento da cui è stata creata l'istantanea. In questo modo, è possibile ricostruire l'aggregato caricando lo snapshot più recente e riproducendo solo gli eventi che ne sono seguiti, invece di riprodurre sempre l'intero flusso di eventi dall'inizio dei tempi.