1. Pregunta
Un flujo de eventos de órdenes se analiza sintácticamente, se divide en ventanas, se agrega y se califica por riesgo. Los resultados se escriben en un almacén de datos (warehouse) y se dispara una notificación downstream. Los workers pueden fallar, las redes pueden agotar el tiempo de espera y los eventos pueden llegar tarde. Explica el límite de exactly-once y diseña un flujo que no genere cargos duplicados durante los reintentos.
2. Restricciones y aclaraciones
- Separa tres capas: entrega de mensajes, resultados dentro del pipeline y efectos secundarios externos.
- Los eventos pueden duplicarse, llegar fuera de orden o retrasarse; un log de procesamiento no es prueba de un resultado confirmado (committed).
- Los resultados deben ser reproducibles, mientras que las notificaciones y otras llamadas externas necesitan idempotencia o deduplicación.
- Aclara la latencia, las ventanas de retraso (lateness windows) y la política de descarte antes de elegir una implementación.
3. Concepto central
El procesamiento exactly-once generalmente significa que el resultado de un registro en el pipeline se refleja como máximo una vez en la salida duradera, al tiempo que el sistema evita perder dicho registro. No significa que cada función de usuario se ejecute una sola vez, ni cubre automáticamente una llamada HTTP, un correo electrónico o una llamada a una base de datos. Una entrada at-least-once combinada con checkpoints, reproducción determinista y deduplicación de resultados puede producir una garantía de salida verificable.
4. Flujo de referencia
onEvent(event):
key = stableEventId(event)
state = readCheckpointOrState(key)
result = deterministicTransform(event, state)
writeTransactionalResult(key, result) # unique(key)
commitCheckpointAfterResult(key)
onExternalSideEffect(result):
idempotencyKey = result.eventId + ":" + result.version
callOrOutbox(idempotencyKey, result.payload)Primero escribe el resultado y el ID del evento en el almacenamiento con una restricción de unicidad o una transacción, y luego avanza el checkpoint. Enruta las notificaciones externas a través de una API idempotente o una outbox con un emisor independiente. El emisor puede reintentar, mientras que el receptor acepta una clave de idempotencia dada solo una vez.
5. Casos de falla y compensaciones
Si un worker falla después de que una llamada externa tiene éxito pero antes de que su checkpoint se confirme, la reproducción llamará al servicio externo nuevamente. Sin una clave de idempotencia, el runner por sí solo no puede eliminar ese efecto secundario duplicado. Los resultados por ventana también dependen de los datos tardíos y de los watermarks, por lo que el límite de corrección debe ser explícito. Garantías end-to-end más estrictas añaden estado de deduplicación, coordinación de transacciones y costo de almacenamiento; si los duplicados son aceptables, at-least-once puede ofrecer una latencia menor.
6. Verificación y observabilidad
- Inyecta fallas, tiempos de espera agotados, mensajes duplicados y eventos fuera de orden; inspecciona el resultado final para una clave de negocio específica.
- Registra los IDs de eventos de entrada, recuentos de intentos, versiones de commit, aciertos de deduplicación y resultados de llamadas externas.
- Reconcilia cuatro métricas: recibidos, procesados, confirmados (committed) y notificados. Los logs de los workers por sí solos son insuficientes.
- Monitorea la tasa de duplicados, el retraso (lateness), la antigüedad de los checkpoints, el tamaño del estado de deduplicación y el backlog de reproducción.
7. Errores comunes
- Tratar la entrega exactly-once, el procesamiento exactly-once y los efectos secundarios exactly-once como una sola promesa.
- Asumir que una opción de configuración del framework otorga efectos de ejecución única a cualquier código personalizado y a APIs externas.
- Deduplicar usando una marca de tiempo en lugar de un ID de evento estable, lo que produce claves diferentes en caso de reintento o reproducción.
- Ignorar eventos tardíos, conflictos de versión y la retención de registros de deduplicación.
8. Criterios de evaluación en entrevistas
Delimita la frontera de la garantía
El candidato separa la entrega, los resultados dentro del pipeline y los efectos secundarios externos, e identifica qué capa cubre realmente el framework.
Diseña un flujo reproducible
El candidato utiliza un ID de evento estable, transformaciones deterministas, confirmación transaccional de resultados y ordenamiento de checkpoints, para luego explicar la recuperación ante caídas.
Maneja efectos secundarios externos
El candidato propone una clave de idempotencia, una restricción de unicidad o una outbox, y explica cómo el emisor y el receptor previenen duplicados de manera conjunta.
Verifica con inyección de fallas
El candidato contempla duplicados, reordenamientos, retrasos, tiempos de espera agotados y caídas de workers, utilizando datos confirmados y reconciliación de negocio para validar la propuesta.