Skip to content

Eventos de dominio & EventBus

El dominio define qué ocurrió (DomainEvent). La aplicación publica a través del puerto EventBus. La infraestructura adapta (Nest EventEmitter hoy; RabbitMQ mañana) y reacciona con handlers.

Incluido cuando scaffoldas con --events (o lo aceptas en el wizard).

Flujo (health-check)

text
HTTP POST /api/v1/health-check/event-emit


EventEmitHealthCheckEndpoint


EventEmitChecker              (application; @Inject(EVENT_BUS_TOKEN))
        │  new EventCheckRequested({ message })
        │  eventBus.emit([event])

EventBusNest → EventEmitter2.emit('event.emit_check_requested', event)


EventCheckRequestedHandler    (infrastructure; @OnEvent)

Piezas base

PiezaRol
DomainEventBase abstracta (id, name, payload, occurredAt)
DomainEventIdExtiende Uuid (UUID v7 semántico)
DomainEventNameVO con formato obligatorio aggregate.action
AggregateRootAcumula eventos (recordEvent / pullEvents)
EventBusPuerto: emit(events)
EVENT_BUS_TOKENToken Nest para inyectar el puerto
EventBusNestAdapter producción vía @nestjs/event-emitter
EventBusMemoryAdapter para tests (TEST_MODE_ENABLED=true)

Cómo añadir un evento nuevo

  1. Crear src/<feature>/domain/events/<Nombre>.ts extendiendo DomainEvent.
  2. Definir static readonly EVENT_NAME = 'aggregate.action'.
  3. Emitir desde un use case con @Inject(EVENT_BUS_TOKEN).
  4. Crear handler en infrastructure/event-handlers/ con @OnEvent(EVENT_NAME).
  5. Registrar handler + use case en el módulo Nest del feature.

Checklist

  1. Evento en domain con EVENT_NAME validado por DomainEventName.
  2. Emisión desde application vía puerto (nunca EventEmitter2 directo).
  3. Handler solo en infrastructure.
  4. Unit test del use case con fake/EventBusMemory.
  5. E2E si el evento se dispara desde HTTP.

Wiring

ts
EventBusModule.init({ disable: loadConfig().testModeEnabled })
EventEmitterModule.forRoot({ global: true })

TEST_MODE_ENABLED=true cambia a EventBusMemory para assertar eventos emitidos sin el emitter real.

Reglas de handlers

  • Viven en infrastructure, no en domain.
  • Suscribirse con @OnEvent(<Event>.EVENT_NAME) coincidiendo exactamente con el string del evento.
  • Mantenerlos finos: side effects / logging / projections; no invariantes de negocio.
  • Registrarlos en providers del feature module.

MIT License · Scaffold from backend-boiler