DDD, Saga y fuente de eventos: ¿Puede una acción de compensación simplemente ser una eliminación en el almacén de eventos?

13

Me doy cuenta de que la pregunta anterior probablemente genera algunos '¿qué?', pero déjame intentar explicarte:

Estoy tratando de envolver mi cabeza en un par de conceptos relacionados, básicamente el patrón Saga ( enlace ) en combinación con Event-sourcing (un concepto DDD: enlace )

Un buen post que lo envuelve junto: enlace

Llego a la pregunta en un minuto, pero creo que primero tengo que intentar resumir lo que entiendo (lo que podría estar mal, así que corríjalo si ese es el caso) ya que esto podría impactar por qué Estoy haciendo la pregunta para comenzar con:

  1. El patrón Saga es un tipo de agente que, dado que una acción (usuario final, automatizado, etc. esencialmente cualquier cosa que vaya a cambiar los datos) divide esa acción en 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 respectivas raíces agregadas para ser atendido.
  2. Estas raíces agregadas pueden operar de forma completamente autónoma (buena separación de inquietudes, gran escalabilidad, etc.)
  3. Una instancia de Saga en sí misma no contiene ninguna lógica de negocios, que está contenida en las raíces agregadas a las que envía las actividades. La única "lógica" contenida en la Saga es la lógica de "proceso", (que a menudo se implementa como un Statemachine), que determina en función de las acciones recibidas (así como los eventos de seguimiento) qué hacer (es decir, qué actividades enviar)
  4. Los patrones Saga implementan un tipo de patrón de transacción distribuida. Es decir: cuando una de las raíces agregadas (que de nuevo funciona de forma autónoma, sin conocer las demás existentes) falla, es posible que la acción completa tenga que revertirse.
  5. Esto se implementa al tener todas las raíces agregadas, al completar su informe de actividades de vuelta a la Saga. (En caso de éxito y error)
  6. En caso de que todas las raíces agregadas devuelvan un éxito, la máquina de estadísticas interna si la Saga determina qué hacer a continuación (o decide que está hecho)
  7. En caso de falla, la Saga emite a todas las raíces agregadas que participaron en la última acción 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.
  8. Esto podría ser simplemente hacer un 'Minus 1 vote' si la acción fue "más 1 voto 'pero podría ser más complicado como restaurar una entrada de blog a su versión anterior.
  9. El aprovisionamiento de eventos (consulte el blogpost que combina los dos) tiene como objetivo externalizar el guardado de los resultados de cada una de las actividades que cada una de las raíces agregadas realiza en un Almacén de eventos centralizado (los cambios se denominan "eventos" en este contexto)
  10. Este almacén de eventos es la "versión única de la verdad" y se puede usar para reproducir el estado de todas las entidades simplemente mediante la iteración de los eventos almacenados (esencialmente como un registro de eventos)
  11. Combinar los dos (es decir, dejar que las raíces agregadas utilicen la fuente de eventos para subcontratar guardando sus cambios antes de informar a la Saga) permite muchas posibilidades agradables, una de las cuales concierne a mi pregunta ...

Sentí que necesitaba sacarme esto de mi hombro, ya que es mucho para agarrarlo de una sola vez. Dado este contexto / mentalidad (de nuevo, corríjalo si es incorrecto)

la pregunta: cuando una raíz agregada recibe una Acción de Compensación y si esa raíz agregada ha subcontratado sus cambios de estado mediante el uso de Evento, la Acción de Compensación en todas las situaciones no sería una eliminación. del último evento en la tienda de eventos para esa raíz agregada dada? (Suponiendo que la implementación persistente permita 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 haya sido demasiado largo.

Gracias.

    
pregunta Geert-Jan 19.07.2012 - 02:23

4 respuestas

7

No debes eliminar los eventos de tu almacén de eventos. Estos representan algo que sucedió. Si algo sucede ahora, también debería saberlo, por lo tanto, agregue un evento que obligue a su agregado a volver a algún estado anterior. Es una pena eliminar la información de su base de datos.

piense en el ejemplo del carro de greg young y los elementos eliminados. Puede ser mañana la información de la acción compensatoria podría ser de cualquier valor ...

En cuanto a la saga, todo es correcto, hasta donde yo sé. Deberías pensar en la saga como en una máquina de estado. Solo hace eso.

Es un comando que la saga está emitiendo para decirle al agregado que haga algo. De esta acción habrá un evento. Este evento podría ser la acción correctiva que necesita, o tal vez deba ser desnormalizado en una vista para que algún usuario lo vea y decida qué hacer.

Depende de tus reglas de negocio. O bien, hay una solución fácil: la raíz agregada sabe que, en tal caso, lo hace, o la elección es demasiado compleja para ser programada (el costo de desarrollo es demasiado alto) y, por lo tanto, puede proponer esto a algún usuario, que Podría elegir entre diferentes acciones. Todo depende del contexto de la acción compensatoria. Se trata de reglas de negocio puras. ¿Qué debemos hacer en este caso o en ese caso? Esto es algo que debe preguntarle a su experto en dominios, y luego elegir con él, si es mejor desarrollar una solución automática o si la solución es preguntarle al usuario Ronald R., porque él es el que responde a esta pregunta generalmente.

    
respondido por el Arthis 19.07.2012 - 14:41
5

Para completar, pensé incluir un fragmento relevante de Martin Fowler sobre las formas de revertir el estado:

  

Además de los eventos que se juegan a sí mismos hacia adelante, a menudo también es útil   para que puedan revertirse ellos mismos.

     

La inversión es la más directa cuando el evento se lanza en el   Forma de una diferencia. Un ejemplo de esto sería "agregar $ 10 a Martin's   cuenta "a diferencia de" establecer la cuenta de Martin en $ 110 ". En el primer   caso puedo revertir simplemente restando $ 10, pero en este último caso   No tengo suficiente información para recrear el valor pasado de la   cuenta.

     

Si los eventos de entrada no siguen el enfoque de diferencia, entonces la   evento debe garantizar que almacena todo lo necesario para la reversión durante   tratamiento. Puede hacer esto almacenando los valores anteriores en cualquier   valor que se cambia, o calculando y almacenando diferencias en   el evento.

De: enlace

    
respondido por el Geert-Jan 19.07.2012 - 19:09
0

Conceptualmente:

  • El evento es algo que sucedió. El pasado no se puede cambiar.
  • El comando es algo que hacer. El comando no puede ocurrir (puede ser rechazado).

Solo podemos cambiar nuestro estado futuro mediante la ejecución de otro comando (Compensate Action) 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":

  • ¿Qué sucede si el último evento no es el que se debe eliminar? ¿Qué pasa si ocurrieron otros eventos después del que se va a eliminar? Estos eventos también deben cambiarse (ya que su estado base habría cambiado al eliminar el evento que se encuentra ante ellos).
  • ¿Qué pasa si el evento fue enviado al sistema externo? Es posible que no tenga acceso para corregir su estado que no sea el envío de otro evento.

En resumen, no tiene opción de eliminar eventos dentro del patrón CQRS.

Puede reducir su almacén de eventos haciendo un estado de instantánea (que se basa en todos los eventos que llevan a ese estado), pero este aspecto físico no tiene nada que ver con el concepto de evento.

    
respondido por el uvsmtid 06.04.2016 - 11:00
0

Geert-Jan, yo también creo que la acción de compensación puede simplemente eliminar el (los) evento (s) correspondiente (s). 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 transacciones de compensación.

Algunos dicen que eliminar el evento viola los "principios" de la fuente de eventos o CQRS. Creo que eso 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:

try {
    newEvents = processMycommand(myCommand)
    for (Event newEvent : newEvents)
        EventStore.insertEvent(newEvent);
} catch (Exception e) {
    EventStore.rollback();
}

Supongamos que su almacén 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 lanzó una excepción. El comando rollback 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 / retrotracció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 (mediante 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 ocurra, especialmente en soluciones de lectura intensiva.

    
respondido por el Paulo Merson 08.06.2016 - 00:23

Lea otras preguntas en las etiquetas