Me doy cuenta de que la pregunta anterior probablemente plantea algunos "¿qué?", Pero déjame intentar explicar:
Estoy tratando de entender un par de conceptos relacionados, básicamente el patrón Saga ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf ) en combinación con Event-sourcing (A DDD-concept : http://en.wikipedia.org/wiki/Domain-driven_design )
Una buena publicación que lo resume: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/
Llegaré a la pregunta en un minuto, pero creo que tengo que intentar resumir lo que entiendo primero (lo cual podría estar mal, así que corríjalo si ese es el caso) ya que esto podría afectar por qué estoy haciendo la pregunta para comenzar:
- El patrón Saga es una especie de intermediario que da una acción (usuario final, automatizado, etc., esencialmente cualquier cosa que vaya a cambiar datos) divide esa acción en las actividades comerciales y envía cada una de estas actividades como mensajes a un Bus de mensajes que a su vez lo envía a las raíces agregadas respectivas para que se cuiden.
- Estas raíces agregadas pueden operar de manera completamente autónoma (buena separación de preocupaciones, gran escalabilidad, etc.)
- Una instancia de Saga en sí no contiene ninguna lógica de negocios, que está contenida en las raíces agregadas a las que envía actividades. La única 'lógica' contenida en la Saga es la lógica de 'proceso' (a menudo implementada como una máquina de estado), que determina en función de las acciones recibidas (así como los eventos de seguimiento) qué hacer (es decir, qué actividades enviar)
- Los patrones de Saga implementan una especie de patrón de transacción distribuida. Es decir: cuando una de las raíces agregadas (que de nuevo funciona de manera autónoma, sin saber de las otras existentes) falla, toda la acción podría tener que revertirse.
- Esto se implementa al tener todas las raíces agregadas, al finalizar su informe de actividad de nuevo a la Saga. (En caso de éxito y error)
- En caso de que todas las raíces agregadas devuelvan un éxito, la máquina de estado interno si la Saga determina qué hacer a continuación (o decide que está hecho)
- En caso de falla, la Saga emite a todas las raíces agregadas que participaron en la última acción una llamada Acción de Compensación, es decir: una acción para deshacer la última acción que hizo cada una de las raíces agregadas.
- Esto podría ser simplemente hacer un 'Menos 1 voto' si la acción fue "más 1 voto", pero podría ser más complicado como restaurar una publicación de blog en su versión anterior.
- El abastecimiento de eventos (consulte la publicación de blog que combina los dos) tiene como objetivo externalizar el almacenamiento de los resultados de cada una de las actividades que cada una de las raíces agregadas lleva a cabo en una Tienda de eventos centralizada (los cambios se denominan 'eventos' en este contexto)
- Esta tienda de eventos es la 'versión única de la verdad' y se puede usar para reproducir el estado de todas las entidades simplemente iterando los eventos almacenados (esencialmente como un registro de eventos)
- La combinación de los dos (es decir, dejar que las raíces agregadas utilicen el abastecimiento de eventos para externalizar el almacenamiento de sus cambios antes de informar a la Saga) permite muchas posibilidades interesantes, una de las cuales se refiere a mi pregunta ...
Sentí que necesitaba sacar esto de mi hombro, ya que es mucho de entender de una vez. Dado este contexto / mentalidad (de nuevo, corrija si está equivocado)
la pregunta: cuando una raíz agregada recibe una Acción compensatoria y si esa raíz agregada ha subcontratado sus cambios de estado utilizando el abastecimiento de eventos, ¿no sería la Acción compensatoria en todas las situaciones simplemente una eliminación del último evento en el Almacén de eventos para eso? dada la raíz agregada? (Suponiendo que la implementación persistente permite eliminaciones)
Eso tendría mucho sentido para mí (y sería otro gran beneficio de esta combinación), pero como dije, podría estar haciendo estas suposiciones basadas en una comprensión incorrecta / incompleta de estos conceptos.
Espero que esto no sea demasiado largo.
Gracias.
fuente
Para completar, pensé incluir un fragmento relevante de Martin Fowler sobre formas de revertir el estado:
De: http://martinfowler.com/eaaDev/EventSourcing.html
fuente
Conceptualmente:
Solo podemos cambiar nuestro estado futuro ejecutando otro comando (Compensar acción) que debería provocar que los eventos cambien el estado de la aplicación.
Para "confundir" la pregunta, piense en esta frase "eliminar del último evento":
En resumen, no tiene la opción de eliminar eventos dentro del patrón CQRS.
Puede reducir su Tienda de eventos haciendo un estado de instantánea (que se basa en todos los eventos que conducen a ese estado), pero este aspecto físico no tiene nada que ver con el concepto de evento.
fuente
Geert-Jan, yo también creo que la acción de compensación simplemente puede eliminar los eventos correspondientes. Tiene sentido y muestra otro beneficio del patrón de diseño de Event Sourcing: una implementación más fácil del patrón de diseño de Compensación de transacciones.
Algunos dicen que eliminar el evento viola los "principios" del abastecimiento de eventos o CQRS. Creo que es una generalización limitante. Creo que está bien eliminar un evento si se creó dentro del alcance de una transacción global que se está cancelando. Considere el pseudocódigo:
Supongamos que su tienda de eventos es una base de datos transaccional. En el pseudocódigo, puede imaginar la situación en la que insertó el primer evento, pero al intentar insertar el segundo evento se produjo una excepción. El comando de reversión revertiría naturalmente la inserción del primer evento. ¿Es eso razonable?
Si es razonable para una transacción de base de datos ACID (transacción con confirmación / reversión), ¿por qué no sería razonable para una transacción compensatoria?
Al ejecutar la transacción global de Saga, los cambios de datos se pueden deshacer (por compensación). No es necesario mantener el evento que se creó durante la transacción porque la transacción no se completó.
Ahora, si la compensación intenta eliminar un evento y ese evento no es el evento más nuevo en un objeto, entonces la eliminación no debería ocurrir. Pero, en general, es poco probable que suceda, especialmente en soluciones de lectura intensiva.
fuente
Juguemos con la idea de que el almacenamiento de eventos son solo datos que desea guardar. Por ejemplo, podemos tener un disco duro, podemos comenzar desde el principio y escribir datos en él. Cada vez que tenemos un evento, agregamos nuestros datos anteriores, así que seguimos escribiendo en el disco donde nos detuvimos la última vez. Cuando queremos eliminar un evento, volvemos, eliminamos esa parte del disco y dejamos un espacio. Retroceder por sí solo ralentiza nuestro almacenamiento de eventos, pero podemos vivir con eso. Si usamos un sistema de archivos, eso intentará llenar el vacío con los últimos eventos, por lo que terminaremos teniendo un almacenamiento fragmentado lento o podemos hacer la desfragmentación. Ninguno de los dos es algo que nos gusta. Si hablamos de bases de datos, obtendrá esto si usa una base de datos relacional en lugar de una base de datos de agregar solo para almacenar sus eventos:
ref: https://cambridge-intelligence.com/bringing-time-series-data-to-life-with-keylines/
De c. por un sitio normal esto no importa, pero estas soluciones están diseñadas para grandes sitios web como Facebook, Google, etc. Así que realmente la pregunta no tiene sentido, porque ¿cómo eliminaría un evento en una base de datos de solo agregar y cómo ¿Llamas compensación a algo así como construir una máquina del tiempo y retroceder en el tiempo para cambiar o prevenir un evento?
Hasta donde se. la única forma de resolver esto es creando un nuevo almacenamiento de eventos donde excluya los eventos que no desea tener y luego elimine el almacenamiento de eventos anterior. Pero esta es una solución extrema para eliminar un solo evento. Si hablamos de GDPR, entonces la única solución relativamente buena que conozco es almacenar datos personales cifrados en el almacenamiento de eventos y eliminar la clave de cifrado de una base de datos diferente.
fuente