Arquitectura Orientada a Eventos (EDA): Fundamentos
En EDA, los servicios se comunican exclusivamente publicando eventos (hechos que ya ocurrieron) en lugar de invocar servicios directamente. Un evento es un dato inmutable que registra algo que sucedió en el dominio: PedidoCreado, PagoConfirmado, StockReservado. Los servicios interesados se suscriben a esos eventos y reaccionan de forma autónoma.
En una línea public sealed interface EventoPedido permits PedidoCreado, PedidoEnviado, PedidoCancelado {}
public record TareaCompletada(long tareaId, String responsable, Instant cuando) {}
@Service
class CompletarTareaService {
private final TareaRepository repo;
private final ApplicationEventPublisher eventos;
private final Clock reloj;
CompletarTareaService(TareaRepository repo, ApplicationEventPublisher eventos, Clock reloj) {
this.repo = repo;
this.eventos = eventos;
this.reloj = reloj;
}
@Transactional
public void completar(long id) {
var tarea = repo.findById(id).orElseThrow();
tarea.completar(reloj);
eventos.publishEvent(new TareaCompletada(id, tarea.getResponsable(), Instant.now(reloj)));
}
}
@Component
class AlCompletarTarea {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) // solo si el commit fue bien
void notificar(TareaCompletada evento) {
notificador.avisar(evento.responsable(), "Tarea " + evento.tareaId() + " completada");
}
}
Cómo funciona por dentro
En una arquitectura orientada a eventos, los servicios se comunican anunciando hechos que han ocurrido (TareaCompletada, PagoRechazado) en lugar de llamarse directamente. El emisor no sabe ni le importa quién escucha. Esto reduce el acoplamiento temporal (el consumidor puede estar caído y procesar más tarde) y permite añadir comportamientos nuevos suscribiéndose a eventos existentes.
Hay dos estilos. En la notificación de eventos, el evento lleva lo mínimo (el id) y quien lo necesite consulta los detalles. En la transferencia de estado, el evento lleva los datos relevantes y los consumidores mantienen su propia copia, sin llamadas de vuelta.
El precio: el flujo de negocio queda repartido entre servicios, es más difícil de seguir y depurar (hace falta trazabilidad distribuida), y los datos son eventualmente consistentes. Dentro de un mismo servicio, Spring ofrece eventos en memoria con ApplicationEventPublisher y @TransactionalEventListener.
Se conecta con DesacoplamientoMicroserviciosKafka/RabbitMQ