Trabajando con eventos

En sistemas modernos, siguiendo buenas prácticas de arquitectura como DDD (Domain-Driven Design) y Clean Architecture, los eventos son mecanismos fundamentales para modelar cambios de estado y la comunicación asíncrona entre componentes o sistemas. Un evento representa algo que ya ha ocurrido en el dominio de la aplicación y que puede ser de interés para otras partes del sistema o servicios externos.

Eventos de Dominio

Los eventos de dominio representan hechos importantes que ocurrieron dentro del contexto de la aplicación. Se generan y consumen internamente en el sistema, permitiendo que los cambios de estado se propaguen de manera desacoplada, es decir, sin que los objetos necesiten conocerse directamente entre sí.

¿Cuándo utilizar un Evento de Dominio?

  • Siempre que una operación genere un cambio significativo en el dominio y sea necesario notificar o activar otras partes del sistema.
  • Para mantener el modelo de dominio cohesionado, permitiendo que diferentes procesos se activen sin crear dependencias directas entre módulos o servicios.

En Lino, crear un nuevo evento de dominio es sencillo. Puede ejecutar:

lino event new

El asistente de CLI solicitará:

  • Servicio – Servicio en el que se creará el evento.
  • Módulo – Módulo en el que se creará el evento (solo en servicios modulares).
  • Entidad – Entidad en la que se creará/asociará el evento.
  • Tipo de evento – Evento de dominio o evento de integración.
  • Nombre del evento – Nombre utilizado en el dominio, asociado a la entidad.

Ejemplo

Al crear el evento de dominio UserCreated asociado a la entidad User, el sistema crea automáticamente un evento con el nombre UserCreatedDomainEvent. Este nombre deja claro a cualquier parte del sistema que consuma el evento que la acción de creación de usuario ya se completó.

Estructura generada por Lino:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Domain/
                ├── MyApp.MyService.Domain.csproj
                └── Aggregates/
                    └── Users/
                        ├── User.cs
                        ├── Errors/
                        ├── Events/
                        │   └── UserCreatedDomainEvent.cs
                        ├── Repositories/
                        └── Resources/

Manejadores de Eventos de Dominio

Un Domain Event Handler es una clase responsable de reaccionar a un Evento de Dominio, ejecutando acciones relacionadas con el estado interno de la aplicación, siempre dentro del mismo contexto transaccional.

El objetivo principal de estos manejadores es mantener el sistema cohesionado y desacoplado, permitiendo que se apliquen reglas adicionales sin sobrecargar la lógica central de la entidad o del agregado.

Por ejemplo, después de crear un User, puede ser necesario actualizar estadísticas, generar un registro interno o notificar a otro agregado. Estas acciones tienen sentido dentro del dominio y pueden ocurrir de manera síncrona, asegurando consistencia inmediata.

Sin embargo, las operaciones que dependen de recursos externos —como el envío de correos electrónicos o llamadas a APIs de terceros— no deben ejecutarse directamente a partir de eventos de dominio, ya que esto ataría la transacción a tareas lentas o inestables. En estos casos, el dominio puede generar un evento de integración (registrado en Outbox), que será procesado posteriormente de manera asíncrona y resiliente.

Características principales:

  • Reacciona a un evento, pero nunca lo modifica.
  • Ejecuta únicamente operaciones in-process relacionadas con la consistencia del dominio.
  • Garantiza que todo se ejecute dentro de la misma transacción.

Para crear un nuevo manejador de eventos de dominio, simplemente ejecute el comando:

lino event-handler new

El asistente de CLI solicitará:

  • Servicio – Servicio en el que se creará el manejador de eventos.
  • Módulo – Módulo en el que se creará el manejador de eventos (solo en servicios modulares).
  • Entidad – Entidad en la que se creará el manejador de eventos.
  • Tipo de evento – Evento de dominio o evento de integración.
  • Evento – Evento que será consumido.
  • Nombre del manejador de eventos – Nombre utilizado que se asociará a la entidad y al evento de dominio.

Ejemplo

Al crear el manejador de eventos de dominio UserCreated asociado a la entidad User y al evento UserCreatedDomainEvent, el sistema crea automáticamente un manejador de eventos con el nombre UserCreatedDomainEventHandler.

Estructura generada por Lino:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Application/
                ├── MyApp.MyService.Application.csproj
                └── UseCases/
                    └── Users/
                        ├── Commands/
                        ├── EventHandlers/
                        │   └── Domain/
                        │       └── UserCreatedDomainEventHandler.cs
                        ├── Logging/
                        ├── Queries/
                        └── Resources/

Eventos de Integración

Los Eventos de Integración son mensajes que indican que algo importante ha ocurrido y deben compartirse con sistemas externos u otros microservicios.

A diferencia de los eventos de dominio, aquí el objetivo es la comunicación entre sistemas y la sincronización de estados.

Cuándo crear un Evento de Integración:

  • Cuando un cambio en tu sistema necesita reflejarse en otro sistema.
  • Cuando tu microservicio necesita publicar cambios para que otros microservicios puedan reaccionar.

Principales diferencias entre Domain Events y Integration Events:

Aspecto Evento de Dominio Evento de Integración
Público objetivo Interno Externo
Acoplamiento Bajo (interno) Necesario (entre sistemas)
Tiempo de procesamiento Inmediato Puede ser asíncrono, con garantías de entrega
Persistencia requerida No obligatoria Sí (para confiabilidad y resiliencia)

En Lino, crear un nuevo evento de integración es sencillo. Puedes ejecutar:

lino event new

El asistente del CLI solicitará:

  • Servicio – Servicio en el cual se creará el evento.
  • Módulo – Módulo en el que se creará el evento (solo en servicios modulares).
  • Entidad – Entidad en la que se creará / asociará el evento.
  • Tipo de evento – Evento de dominio o evento de integración.
  • Nombre del evento – Nombre utilizado para el evento de integración, asociado a la entidad.

Ejemplo

Creando el evento de integración UserCreated asociado a la entidad User, el sistema crea automáticamente un evento con el nombre UserCreatedIntegrationEvent. Este nombre deja claro para cualquier parte del sistema que consuma el evento que la acción de creación del usuario ya se ha completado.

Estructura generada por Lino:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── IntegrationEvents/
                ├── MyApp.MyService.IntegrationEvents.csproj
                └── Users/
                    └── UserCreatedIntegrationEvent.cs

Manejadores de Eventos de Integración

Un Integration Event Handler es una clase responsable de consumir un Evento de Integración, normalmente publicado por otro servicio o contexto, y luego ejecutar acciones específicas en su propio dominio.

Estos manejadores reciben eventos a través de mecanismos de mensajería (como RabbitMQ, Kafka, Azure Service Bus, etc.), generalmente junto con el patrón Outbox, que garantiza una entrega confiable y procesamiento asíncrono.

Por ejemplo, cuando un evento UserCreated es publicado por un servicio de Identidad, el manejador correspondiente en otro contexto puede reaccionar enviando un correo electrónico de bienvenida o llamando a APIs externas. Estas operaciones pueden ser más lentas o propensas a fallos, pero al manejarse fuera de la transacción principal, no comprometen la consistencia interna de la aplicación.

Características principales:

  • Reacciona a eventos que representan hechos de negocio relevantes para otros contextos.
  • Ejecuta operaciones que pueden ser lentas o externas (por ejemplo: envío de correos electrónicos, llamadas a APIs).
  • Se procesa de manera asíncrona y resiliente, a menudo con reintentos y monitoreo.
  • Asegura que fallos externos no afecten la transacción original del dominio.
  • Facilita la integración entre bounded contexts y sistemas distribuidos.

Para crear un nuevo manejador de eventos de integración, simplemente ejecute el comando:

lino event-handler

El asistente de CLI solicitará:

  • Servicio – Servicio en el cual se creará el manejador de eventos.
  • Módulo – Módulo en el que se creará el manejador de eventos (solo en servicios modulares).
  • Entidad – Entidad en la que se creará el manejador de eventos.
  • Tipo de evento – Evento de dominio o evento de integración.
  • Servicio – Servicio en el que existe el evento que se consumirá.
  • Módulo – Módulo en el que existe el evento que se consumirá (solo en servicios modulares).
  • Entidad – Entidad en la que existe el evento que se consumirá.
  • Evento – Evento que se consumirá.
  • Nombre del manejador de eventos – Nombre que se asociará a la entidad y al evento de integración.

Ejemplo

Creando el manejador de eventos de integración SendEmailOnUserCreated asociado a la entidad User y al evento UserCreatedIntegrationEvent, el sistema crea automáticamente un manejador de eventos con el nombre SendEmailOnUserCreatedIntegrationEventHandler.

Estructura generada por Lino:

MyApp/
└── src/
    └── Services/
        └── MyService/
            └── Application/
                ├── MyApp.MyService.Application.csproj
                └── UseCases/
                    └── Users/
                        ├── Commands/
                        ├── EventHandlers/
                        │   └── Integration/
                        │       └── SendEmailOnUserCreatedIntegrationEventHandler.cs
                        ├── Logging/
                        ├── Queries/
                        └── Resources/
Se ha producido un error no controlado. Recargar 🗙