Normalmente un servicio de comandos termina actualizando la base de datos y solemos necesitar que esta actualización sea atómica para evitar inconsistencia en los datos o bugs.
Cuando trabajamos en modelos distribuidos solemos aplicar un Fire&Forget, pero a veces este modelo no es aplicable si tenemos dominios complejos o necesitamos propagar los eventos en un modelo "Domain Event" entre los diferentes dominios para completar un "ciclo completo de trasaccionalidad".
Hay algunos patrones en los que nos podemos apoyar para solucionar esta problemática y que son: SAGA y Outbox Pattern. Aunque ambos tienen sus pros y contras, ambos tienen un problema cuando nuestro sistema procesa Zillions de mensajes de un Topic de Kafka. Y es por ejemplo en el de OutBox Pattern, donde podemos sufrir un backpressure en el sistema
Si ademas le añadimos donde el 2PC noes una opción, debemos buscar patrones alternativos, en este caso llamado "Event Sink".
Descripción
Un mensaje es enviado por una petición de creación desde un servicio externo o llamada REST.
Este mensaje pasará por un servicio de validación que deberá asegurar que los datos del mensaje puede ser almacenado en la bbdd, debe validar tanto el contenido como la capacidad de persistencia. Para conseguir el resultado, es posible que deba apoyarse en patrones CQRS (sobre todo en la parte del query) para verificar el contenido. En caso de no cumplir con la validación puede ir a una DLT para un tratamiento posterior.
Todos los mensajes validados quedan en un Topic para ser procesados, por un lado por una capa separada que inserta estos mensajes en la base de datos sin mayor requerimiento que la propia actualización, siendo un proceso muy ligero, bajo coste y baja latencia. Por otro lado, los mensajes quedan dispuestos para cualquier otro consumidor que necesite los datos para continuar con el proceso de negocio.
De esta manera, aunque la bbdd tenga n milliones de mensajes que procesar y persistir, el flujo de eventos puede continuar por el sistema.
Pros y contras
Pros
- Admite Zillions de mensajes
- Baja latencia
- Evita el backpressure
- No interrumpe el proceso de negocio
- Las transacciones con la base de datos son atómicas
Contras
- Requiere de una mayor control de errores
- Es necesario una infraestructura compleja
- El sistema puede quedar eventualmente inconsistente, con lo que es necesario tener algún mecanismo de compensación
- Al tener varios topics con la misma información, tendremos volúmenes duplicados de información.
Modelos de persistencia genérico
Otro punto interesante de este patrón es el referido al propio Sink Service, al implementar este modelo, es posible diseñar un sistema capaz de procesar en base datos cualquier entidad del modelo de dominio sin necesidad de realizar capas adicionales de diseño de DPO's. Esto se debe a que la capa de SSINK cumple con la parte operaciones de SRP básicos de entidades, dejando al lado del Query Segregation (CQRS) la especialización funcional requerida por el dominio funcional del negocio.
Al implementar un modelo genérico en el sistema, solo tendremos que preocuparnos de montar un diseño de validación y consultas específico por dominio.
Este sistema de SINK Genérico es "escalable" para todo el sistema.
Top comments (2)
Marcos,... ¿esto no es como un CQRS, quizás un patrón un poco especializado de ese modelo? quiero decir, una vez el mensaje (comando) llega al sistema y se valida se convierte en evento (como digo yo a veces "eso ya va a misa") y se publica de forma que se pueden actualizar las vistas de lectura que lo necesiten y, aparte, el modelo que es donde entra el "Event Sink".
Es verdad que todos estos patrones y modelos siempre tienen cosas en común o parecidas, claro,....
Muy buen punto de vista.
Para mi CQRS es un patrón de segregación, que puede venir implementado antes o como parte de este patrón. En este caso....el objetivo es que la parte del Command no venga delimitado por el evento y que la transacción contra la bbdd no afecte al resto del flujo de negocio partiendo en dos elementos diferentes.
Por norma se suele utilizar como fuente de "verdad" o datos consolidados una BBDD, pero en este caso, nuestros datos consolidados ya es un topic de kafka.