Entonces, ¿qué me estoy perdiendo?
Adivinando.
Lo primero que puede faltar es que solo necesita volver a cargar los eventos para el estado que está reconstruyendo. Si puede modelar los límites de su transacción de manera limpia, cada objeto puede escribir eventos etiquetados con su propia identificación y luego volver a leer solo esos eventos. Usando una base de datos relacional para el almacenamiento de eventos, habría una columna de identificación indexada para acelerar esa consulta. Usando EventStore, cada objeto tendría su propia secuencia.
Es necesario tener cuidado en su modelo para hacer esto limpiamente, ya que desea asegurarse de que solo está modificando un solo objeto en cada transacción y, por lo tanto, debe tener cuidado de aislar correctamente cada invariante que está intentando hacer cumplir.
En los casos en que eso no sea lo suficientemente rápido, aún tiene la posibilidad de crear instantáneas de su estado (memorización) y persistir en el "almacenamiento tradicional". Cada instantánea se etiqueta con el número de secuencia del último evento utilizado para construir la instantánea; Al recargar, el repositorio toma primero la instantánea y luego le aplica los eventos más nuevos. (Esto implica una forma razonable de capturar las instantáneas más recientes, ya sea que los eventos también estén etiquetados con el número de secuencia o que tenga una forma eficiente de leer el flujo de eventos hacia atrás hasta llegar a su punto de partida).
Todavía hay una ventaja sobre el enfoque habitual aquí, ya que sus instantáneas se pueden construir en paralelo a sus escritos, en lugar de fusionarse con ellos: simplemente coloca un detector de eventos en algún otro hilo / proceso, y lo deja alegremente mientras escribe a la tienda de instantáneas en cualquier horario que parezca razonable. Después de todo, la instantánea no necesita ser particularmente oportuna, solo con la frecuencia suficiente para que el trabajo de volver a aplicar los eventos más nuevos no arruine su SLA.
(Las instantáneas complican la migración; cualquier cambio en la serialización del modelo invalidará el caché de instantáneas. Por supuesto, puede reconstruir instantáneas utilizando la nueva serialización como parte de la migración y luego "ponerse al día" cuando los cambios se activen).
¿La restauración del estado de la secuencia de eventos incluso se realiza comúnmente?
Sí lo es. Lo que normalmente se muestra en los ejemplos de CQRS es que la capa de aplicación, después de asegurarse de que el comando enviado está bien formado, la capa de aplicación cargará el objeto de dominio desde un repositorio, donde la carga es un constructor predeterminado seguido de una reproducción del flujo de eventos (o equivalente, una llamada a una fábrica con una lista de eventos).
Otros dos pensamientos contradictorios.
- Podría haber un caché detrás de la interfaz del repositorio
- La invalidación de caché es uno de los dos problemas difíciles.