design patterns - simplified - Cómo administrar los cambios de ViewModel en una arquitectura de CQRS+Event Sourcing
event sourcing pattern (4)
Actualmente estamos evaluando las arquitecturas CQRS y Event Sourcing. Estoy tratando de entender cuáles son las implicaciones de mantenimiento de usar este tipo de diseño. Dos preguntas a las que me cuesta encontrar respuestas son las siguientes:
1) ¿Qué sucede si, después de que una aplicación haya estado en funcionamiento durante un tiempo, hay un nuevo requisito para agregar un campo adicional a un ViewModel en la base de datos ReadModel? Por ejemplo, el código postal del cliente es obligatorio en el modelo de vista de lista de clientes, donde no se encontraba anteriormente. Por lo tanto, la columna adicional se puede agregar fácilmente a la base de datos de ViewModel, pero ¿cómo se completa esto? Por lo que puedo ver, la única forma es borrar la base de datos de lectura y reproducir todos los eventos desde cero para crear una copia de seguridad de la base de datos ReadModel. Pero, ¿qué pasa si la aplicación ha estado funcionando durante meses o años (como esperamos que lo haga)? Esto podría ser millones de eventos para reproducir, solo para agregar datos para una columna de código postal.
Tengo la misma preocupación si, por alguna razón técnica, la base de datos ReadModel no está sincronizada, o si queremos agregar una nueva base de datos ReadModel. Parece que cuanto más antigua es la aplicación, y cuanto más se usa, más difícil y más costoso es obtener un readmodel actualizado. ¿O me estoy perdiendo un truco en alguna parte? ¿Algo así como las instantáneas de ReadModel?
2) ¿Qué sucede si después de que se hayan reproducido todos los millones de eventos para crear una copia de seguridad de la base de datos de lectura, algunos de los datos no coinciden con lo que se esperaba (es decir, se ve mal)? Se piensa que quizás un error en algún lugar en el evento de almacenamiento, o desnaturalización de las rutinas puede haber causado esto (y parece que si hay una cosa en la que se puede confiar en la codificación, es errores). ¡Cómo hacer para depurar esto! Parece una tarea imposible. O tal vez, de nuevo, me esté perdiendo un truco.
Me interesaría saber de alguien que haya estado ejecutando un sistema como este durante un tiempo, cómo le han funcionado las rutas de actualización y mantenimiento.
Gracias por cualquier momento y entrada.
La belleza de usar la fuente de eventos con CQRS es la capacidad de destruir el modelo de lectura y reconstruirlo desde cero, como se ha mencionado. Por alguna razón, la gente tiene la idea de que pasará mucho tiempo después de que supere un número arbitrario de eventos. Si está utilizando una base de datos relacional para sus modelos de lectura, y lo más probable es que lo sea, es fácil abrir una transacción, leer todos los eventos a través de los manejadores y luego confirmar la transacción. Solo cuando la transacción se compromete, realmente tocamos el disco. Todo lo demás se realiza en la memoria para que pueda ser muy rápido. De hecho, no me sorprendería ver cómo su sistema arranca a través de unos pocos millones de eventos en solo unos minutos, si es así.
La reconstrucción de sus modelos de lectura desde cero debe mostrarse exactamente de la misma manera que su método cotidiano de desnormalizar los eventos en los modelos de lectura. Si no, tienes un error en el código de desnormalización de tu modelo de lectura. Lo bueno aquí es que, desde la perspectiva de su manejador de mensajes, no hay diferencia entre recibir y denormalizar un evento en el modelo de lectura durante los escenarios normales / de producción y en los escenarios de reconstrucción del modelo de lectura.
Si encuentra errores, puede depurar fácilmente mediante la transmisión / copia de los eventos de producción a su estación de trabajo local, estableciendo puntos de interrupción en sus manejadores y luego ejecutando esos eventos a través del código de manejo del modelo de lectura.
Soy algo nuevo en CQRS, por lo que puede que esta no sea la ruta más recomendable (pero iirc lo recogí de una de las listas de correo de CQRS / DDDD).
Creamos un comando y el controlador correspondiente específico para el propósito que se espera que se ejecute una vez que se desapruebe.
En el controlador, usamos el mecanismo que sea más conveniente, por lo que en su caso de agregar un campo de código postal, podemos ejecutar una consulta única que extrae los códigos postales en ese momento de otro modelo de vista y rellena la nueva columna. No nos preocupamos demasiado por la pureza arquitectónica en estos escenarios, ya que se espera que sea una operación única ( Rob Conery''s Massive se ha utilizado con éxito en estas situaciones).
También es posible agregar un evento de red en su modelo. Esto se puede ejecutar como una tarea arbitraria después de que se hayan recibido X eventos (digamos 500)
Para reconstruir, usted empuja sus eventos en una pila hasta que alcanza el evento de red, esto se usa como línea de base, desde aquí saca los eventos de su pila agregando sus valores con su evento de línea de base.
Todavía no tengo una aplicación lista para producción que use cqrs con la fuente de eventos, así que aquí está mi experiencia tratando de crear una.
1) Read Model rebuild
. Sí, básicamente tienes que reconstruir todo el DB del Modelo de Lectura una vez que algo cambia. Y si hay muchos eventos, esto puede llevar mucho tiempo. Por lo tanto, la reconstrucción del modelo de lectura debe estar altamente optimizada (usar lotes de eventos, etc.). Creo que la fuente de eventos se adapta mejor en los casos en que hay una alta proporción de lectura-escritura. Por lo tanto, para algunos datos extremadamente volátiles, puede ser conveniente no almacenarlos como eventos de dominio. Pero entonces la pregunta sobre la capacidad de almacenamiento tampoco está tan lejos. En cualquier caso, puede aplicar cqrs a solo una parte del sistema, la que mejor se ajuste (por ejemplo, probablemente no almacenaría la imagen gráfica como parte del evento).
2) Debugging
. Es altamente improbable que haya un error en el almacenamiento de eventos (debería ser una preocupación del marco), y siempre es fácil verificar qué eventos hay en la tienda. En cuanto al comando para producir eventos esperados, debe tener pruebas aquí, y estas pruebas probablemente serán las más valiosas en el sistema. Para los desnormalizadores, también podría realizarse pruebas, pero no me molestaría en escribir pruebas para los desnormalizantes triviales si su corectitud puede verse a simple vista. Dicho esto, utilicé el depurador varias veces para encontrar problemas en algunos desnormalizadores más complicados; no fue tan divertido tratar de determinar qué evento hace que las cosas salgan mal.