Estamos utilizando CQRS con EventSourcing.

En nuestra aplicación podemos agregar recursos (es un término comercial para un solo elemento) desde la interfaz de usuario y estamos enviando el comando correspondiente para agregar recursos.

Entonces tenemos x número de recursos presentes en la aplicación que se agregaron anteriormente. Ahora, tenemos un tipo especial de recurso (lo llamo SpecialResource). Cuando agregamos este SpecialResource, la identificación debe estar vinculada con todos los recursos existentes en la aplicación. Vinculado significa que este recurso especial debe tener una lista de identificadores (guids) (lista) de recursos existentes.

La solución que intentamos obtener todos los identificadores de recursos en la aplicación antes de agregar el recurso especial (es decir, antes de disparar el comando AddSpecialResource). Asigne esta lista a SpecialResource, luego envíe el comando AddSpecialResource.

Pero no se supone que lo hagamos, porque según el comando cqrs no debería consultar. Es decir. El comando no puede depender de la consulta, ya que la consulta puede tener registros obsoletos.

¿Cómo podemos lograr este escenario empresarial sin consultar los registros existentes en la aplicación?

3
Roshan 30 ene. 2016 a las 09:09

4 respuestas

La mejor respuesta

Pero no se supone que lo hagamos, porque según el comando cqrs no debería consultar. Es decir. El comando no puede depender de la consulta, ya que la consulta puede tener registros obsoletos.

Esto no es del todo correcto.

Los "comandos" ejecutan consultas todo el tiempo. Si está utilizando la fuente de eventos, en la mayoría de los casos, sus comandos son consultas: "si este comando estuviera permitido, ¿qué eventos se generarían?"

La diferencia entre esto y la situación que describió es el límite agregado, que en un dominio de origen de eventos es un nombre elegante para el flujo de eventos. Un agregado puede ejecutar una consulta en su propio flujo de eventos (es decir, su propio estado) al procesar un comando. Son los otros agregados (flujos de eventos) los que están fuera de los límites.

En términos prácticos, esto significa que si SpecialResource realmente necesita ser coherente transaccionalmente con los otros ID de recursos, entonces todos esos datos deben ser parte del mismo agregado y, por lo tanto, parte del mismo evento. stream, y todo desde ese punto es bastante sencillo.

Entonces, si ha estado modelando los recursos con flujos separados hasta este punto, y ahora necesita que SpecialResource funcione como lo ha descrito, entonces tiene un cambio bastante significativo por hacer en su modelo de dominio.

La buena noticia: probablemente ese no sea su requisito real. Considere lo que ha descrito hasta ahora: si resourceId: 99652 se crea un milisegundo antes de SpecialResource, entonces debería incluirse en el estado de SpecialResource, pero si se crea un milisegundo después, no debería. Entonces, ¿cuál es el costo para la empresa si el recurso se creó un milisegundo antes de que se pierda el recurso especial?

Porque, a priori, eso no suena a algo que deba ser demasiado caro.

Más comúnmente, el requisito real se parece más a "SpecialResource necesita incluir todos los identificadores de recursos creados antes del cierre del negocio", pero en realidad no necesita SpecialResource hasta 5 minutos después del cierre del negocio. En otras palabras, aquí tiene un SLA y puede usar ese SLA para informar mejor a su comando.

¿Cómo podemos lograr este escenario empresarial sin consultar los registros existentes en la aplicación?

Voltealo; ejecute la consulta, copie los resultados de la consulta (los ID de recursos) en el comando que crea SpecialResource, luego envíe el comando para que se pase a su modelo de dominio. El comando CreateSpecialResource incluye dentro de él la lista correcta de identificadores de recursos, por lo que el agregado no necesita preocuparse por cómo descubrir esa información.

1
VoiceOfUnreason 28 feb. 2016 a las 07:10

Puede hacer dos cosas para resolver ese problema:

  • haga una distinción entre modelo de lectura y escritura. ¿Sabes qué es el modelo de lectura, verdad? Entonces, "escribir modelo" de datos en contraste es una combinación de estructuras de datos y comportamientos que es suficiente para hacer cumplir todos los invariantes y generar eventos consistentes como resultado de cada comando ejecutado.

  • no tome una regla que dice que "Event Store es una única fuente de verdad" demasiado literalmente. Considere la siguiente interpretación: ES es una fuente única de TODA la verdad para su aplicación, sin embargo, para cada comando específico puede crear "modelos de escritura" que proporcionarán la "verdad" suficiente para que este comando sea consistente.

0
IlliakaillI 30 ene. 2016 a las 22:31

No creo que ningún sistema informático vaya a ser 100% consistente simplemente porque la vida no funciona ni puede funcionar así. Aparentemente, todos también vivimos en el pasado, ya que su cerebro necesita tiempo para procesar la información.

El punto es que haga lo mejor que pueda con la información disponible, pero asegúrese de que su sistema pueda suavizar cualquier borde. Entonces, si necesita asociar uno o dos recursos con su SpecialResource, entonces debería poder hacerlo.

Entonces, incluso si pudiera asociar su SpecialResource con todas las entradas existentes en su almacén de datos, ¿qué quiere decir que no hay otro recurso que aún no se haya ingresado en el sistema que también necesite estar asociado.

Todo, como de costumbre, dependerá de su caso de uso específico. Esta es la razón por la que los administradores de procesos, junto con su estado, le permiten a uno masajear ese estado hasta que el proceso pueda completarse.

Espero no haber malinterpretado tu pregunta :)

0
Eben Roux 30 ene. 2016 a las 09:59

Es difícil saber de qué es capaz su base de datos, pero la forma más consistente de agregar una "instantánea" es en la capa de la base de datos, porque no hay otro lugar común en CQRS puro para eso. (Hay algunos artículos sobre cómo hacer instantáneas de CQRS + ES, si eso es lo que realmente intenta lograr con SpecialResource).

Una forma puede ser materializar la lista de identificadores utilizando algún tipo de procedimiento almacenado con la llegada del comando AddSpecialResource (en la base de datos).

Otra forma es capturar "todos los recursos existentes (hasta el momento)" con algún marcador (marca de tiempo), nunca eliminar los recursos antiguos y agregar la condición "SpecialResource" en las consultas, que utilizarán los datos de SpecialResource.

Ok, una opción más (depende de su caso) es tener siempre a mano la lista de identificadores con la misma consulta, que sirvió a la interfaz de usuario. De esta manera, la definición de "todos los recursos" cambia a "todos los recursos tal como los ve el usuario (en algún momento)".

0
Roman Susi 30 ene. 2016 a las 07:19