Quindi, cosa mi sto perdendo?
Indovinare.
La prima cosa che potresti perdere è che devi solo ricaricare gli eventi per lo stato che stai ricostruendo. Se è possibile modellare in modo pulito i limiti delle transazioni, ogni oggetto può scrivere gli eventi contrassegnati con il proprio ID e quindi rileggere solo quegli eventi. Usando un database relazionale per l'archiviazione di eventi, ci sarebbe una colonna id indicizzata per velocizzare quella query. Usando EventStore, ogni oggetto avrebbe il suo flusso.
Ci vuole un po 'di cura nel tuo modello per farlo in modo pulito, poiché vuoi essere sicuro che stai modificando solo un singolo oggetto in ciascuna transazione, e quindi devi fare attenzione a isolare correttamente ogni invariante che stai cercando di imporre.
Nei casi in cui ciò non è abbastanza veloce, hai ancora la possibilità di creare istantanee del tuo stato (memoization) e persistere in "archiviazione tradizionale". Ogni istantanea viene taggata con il numero progressivo dell'ultimo evento utilizzato per creare l'istantanea; al ricaricamento, il repository acquisisce prima l'istantanea, quindi applica eventi più recenti. (Ciò implica un modo ragionevole per catturare le istantanee più recenti: o gli eventi sono anche taggati con il numero di sequenza, oppure hai un modo efficace per leggere il flusso di eventi all'indietro fino ad arrivare al punto di partenza.)
C'è ancora un vantaggio rispetto al solito approccio qui, dato che le tue istantanee possono essere costruite parallelamente alle tue scritture, piuttosto che essere fuse con loro: hai semplicemente messo un listener di eventi in qualche altro thread / processo e lo hai lasciato allegramente lungo la scrittura al negozio di istantanee su qualsiasi programma sembra ragionevole. Dopotutto, l'istantanea non deve essere particolarmente tempestiva - abbastanza spesso che il lavoro di riapplicare gli eventi più recenti non fa esplodere il tuo SLA.
(Le snapshot complicano la migrazione; eventuali modifiche alla serializzazione del modello invalideranno la cache delle snapshot. Naturalmente, è possibile ricostruire snapshot utilizzando la nuova serializzazione come parte della migrazione e quindi "recuperare" quando le modifiche diventano attive.)
Il ripristino dello stato dal flusso di eventi è anche comunemente eseguito?
Sì. Ciò che normalmente viene mostrato negli esempi CQRS è che il livello Applicazione, dopo aver verificato che il comando inviato sia ben formato, il livello applicazione caricherà l'oggetto di dominio da un repository, dove il carico è un costruttore predefinito seguito da una riproduzione del flusso di eventi (o equivalentemente, una chiamata a una fabbrica con un elenco di eventi).
Altri due pensieri contraddittori.
- Potrebbe esserci una cache dietro l'interfaccia del repository
- L'invalidazione della cache è uno dei due problemi principali.