Estamos comenzando un nuevo proyecto en el que queremos implementar la arquitectura CQRS + Event Sourcing con MongoDB. Ya tenemos algo de experiencia con el enfoque CQRS: en nuestro proyecto anterior tomamos el marco Fohjin como punto de partida (bueno, lo refactorizamos significativamente). Usamos Oracle como almacenamiento y también implementamos un 2PC con TransactionScope en ese caso.

Pero para nuestro nuevo proyecto queremos usar MongoDB debido a su escalabilidad y rendimiento. Definitivamente queremos usarlo para la parte de lectura (informe) y cosiderarlo para una tienda de eventos. La alternativa aquí es usar SQL Server para el almacenamiento de eventos. Así que tenemos que tomar una decisión. Lo que no me gusta de la solución híbrida es TransactionScope, que es costoso y lento y es necesario admitir diferentes tipos de Db (Mongo y SQL).

Observamos NCQRS, pero parece que no queremos depender mucho de ningún marco, lo que dicta muchas cosas que se pueden implementar de manera diferente desde nuestro punto de vista. Así que ahora estamos pensando en algo más ligero como Event Store de Jonathan Oliver. Me gusta el concepto de transmisiones y confirmaciones y también es compatible con MongoDB. Lo que todavía no entiendo, cómo maneja todas esas cosas de 2PC (se dice, eso para NoSQL). En nuestro caso, necesitamos enviar eventos a varios controladores de eventos: algún tipo de denominador que actualice la base de datos de lectura y el programador de tareas para ciertos tipos de eventos. Si algo sale mal con estos controladores y obtenemos una excepción, no hay forma de revertir una confirmación para MongoDB. ¿Hay algún truco para manejar esto?

Agradezco cualquier comentario sobre cómo tomar la decisión correcta y cuáles son los pros y los contras.

4
Voice 18 abr. 2012 a las 01:00

1 respuesta

La mejor respuesta

EventStore utiliza un Guid para identificar de forma única una confirmación en la base de datos para evitar que el mismo flujo de eventos persista más de una vez. Por lo general, este Guid está incrustado directamente en un mensaje, identificando de manera única ese mensaje en particular, y se puede usar como CommitId al llamar a CommitChanges en el flujo de eventos. Puede usar un enfoque similar al manejar eventos en el lado de la consulta de su sistema.

Más información sobre 2PC y cómo evitar transacciones distribuidas:

4
Elliot Ritchie 18 abr. 2012 a las 05:10
Gracias por tu respuesta, Elliot. Hasta donde tengo entendido, necesito hacer que mis manejadores de eventos / enlaces de canalización sean idempotentes, agregando algún tipo de filtro que determinará que el evento / compromiso ya se envió. Suena como agregar mucho código extra para cada controlador (bueno, tal vez se pueda implementar como un aspecto o algo así). Busides, agrega una nueva consulta db para cada controlador, para verificar. Pero bueno, podemos llamarlo "un costo de la solución". Otra pregunta es ¿cuándo manejar eventos / confirmaciones parcialmente manejados?
 – 
Voice
19 abr. 2012 a las 09:05
Sí, necesitará construir la infraestructura para que sus propios controladores de eventos sean idempotentes. Una forma de hacerlo sería incrustar una identificación única en sus eventos e incluir esta identificación en su modelo de lectura; luego podrá saber si ha manejado un evento más de una vez.
 – 
Elliot Ritchie
19 abr. 2012 a las 15:57