Dato che non si specifica quale sarebbe lo scopo del database di "scrittura", assumerò qui che ciò che intendi è questo: quando registri un nuovo aggiornamento a un aggregato, invece di ricostruire l'aggregato dall'evento archivia, lo sollevi dal database "scrivi", convalidi la modifica ed emetti un evento.
Se questo è ciò che intendi, allora questa strategia creerà una condizione di incoerenza: se un nuovo aggiornamento avviene prima che l'ultimo abbia avuto la possibilità di inserirlo nel database "write", il nuovo aggiornamento finirà per essere convalidato 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à stato preso - questo è ciò che chiami "convalida". Per fare ciò, memorizzi una lista di posti già prenotati nel database "scrivi". Quindi, quando arriva una richiesta di prenotazione, si controlla se il posto richiesto è nella lista, e in caso contrario, si emette un evento "prenotato", altrimenti si risponde con un messaggio di errore. Quindi esegui un processo di proiezione, in cui ascolti gli eventi "prenotati" e aggiungi i posti prenotati all'elenco nel database "scrivi".
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, se le richieste arrivano troppo rapidamente e il passaggio 5 si verifica prima del punto 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 devi mai convalidare gli aggiornamenti rispetto a una proiezione. Per convalidare un aggiornamento, si ricostruisce l'aggregato dall'archivio degli eventi, quindi si convalida l'aggiornamento con esso. Successivamente, si emette un evento, ma si utilizza la protezione timestamp per assicurarsi che non siano stati rilasciati nuovi eventi dall'ultima volta in cui si è letto dal negozio. Se fallisce, riprova.
La ricostruzione di aggregati dall'archivio eventi potrebbe comportare una penalizzazione delle prestazioni. Per mitigarlo, è possibile archiviare istantanee aggregate direttamente nel flusso di eventi, taggato con l'ID dell'evento dal quale è stata creata l'istantanea. In questo modo, puoi ricostruire l'aggregato caricando lo snapshot più recente e ripetendo solo gli eventi successivi, invece di riprodurre sempre l'intero flusso di eventi dall'inizio del tempo.