Cuando los sistemas crecen, una arquitectura basada en eventos puede volverse difícil de coordinar. Surgen preguntas como: ¿qué pasa si un evento falla?, ¿cómo asegurar consistencia entre servicios?, ¿cómo depurar una cadena de eventos?
1. Patrón Saga
El patrón Saga permite coordinar una transacción distribuida a través de eventos. Cada servicio realiza una acción y publica un nuevo evento para el siguiente paso.
Ejemplo: proceso de pago en un marketplace
PedidosServicepublicapedido.creadoPagosServiceescucha, cobra y emitepago.confirmadoEnviosServiceescuchapago.confirmadoy despacha el producto
Si un paso falla (por ejemplo, el pago), se dispara una compensación (cancelar pedido).
// PagosService
try {
$this->procesarPago($pedidoId);
$broker->publicar('pagos', json_encode(['tipo' => 'pago.confirmado', 'pedido_id' => $pedidoId]));
} catch (Exception $e) {
$broker->publicar('pagos', json_encode(['tipo' => 'pago.fallido', 'pedido_id' => $pedidoId]));
}
2. Trazabilidad
Registrar todos los eventos en una tabla event_log ayuda a depurar flujos y evitar pérdidas:
DB::table('event_log')->insert([
'tipo' => $evento['tipo'],
'payload' => json_encode($evento),
'fecha' => now(),
]);
También se puede usar OpenTelemetry para visualizar la cadena completa de eventos.
3. Idempotencia
Cada microservicio debe procesar eventos una sola vez aunque lleguen duplicados.
Se logra registrando un event_id único y evitando reprocesamiento.
4. Buenas prácticas
- Usar un esquema estándar de eventos (
tipo,id,timestamp,payload) - Incluir metadatos de rastreo (
trace_id) - Implementar dead-letter queues para eventos fallidos
- Evitar dependencias cíclicas entre servicios
En resumen, orquestar eventos correctamente permite construir sistemas escalables, resilientes y auditables, con un flujo de negocio claro incluso en entornos distribuidos.