Atlasingeniería

Code review en la prácticaRobustez donde el usuario es impredecibleTema 4

Efectos ya aplicados cuando el proceso falla a la mitad

Se descontó el cupón, se mandó el correo y después falló la confirmación. En el cliente no hay transacciones, así que el orden de las operaciones y qué se puede deshacer se vuelven una decisión de diseño.

Un flujo con cuatro pasos: validar, reservar, cobrar, confirmar. El tercero falla. Los dos primeros ya pasaron y dejaron efectos en el mundo: una reserva tomada, un cupón consumido, quizá un correo enviado.

En una base de datos esto se resuelve con una transacción. En un flujo repartido entre el cliente, varios servicios y un proveedor externo, no hay transacción: hay que decidir a mano qué pasa con lo que ya ocurrió.

Cómo se ve en una review

El códigoEl problema que esconde
Un `try` que envuelve cuatro llamadas y un solo `catch` que muestra un error genéricoNo se sabe cuál falló ni qué quedó aplicado
El estado local se actualiza antes de que el servidor confirmeLa pantalla muestra algo que no pasó
Un reintento sobre una operación que no es idempotenteDoble cobro, doble reserva, doble correo
Efectos irreversibles al principio del flujoCuando algo falla, ya no hay forma de volver atrás
El tercero es el que genera incidentes con dinero de por medio.

El más común es el segundo, con nombre propio: la actualización optimista de la interfaz. Está bien —hace que la aplicación se sienta rápida— siempre que exista el camino de revertir cuando el servidor rechaza, y ese camino es justo el que falta.

El orden importa más que el manejo de errores

La mayor parte de estos problemas se evita ordenando las operaciones antes de escribir un solo catch.

La regla del orden

  1. Todo lo reversible primero. Validaciones, reservas temporales, cálculos.
  2. Lo irreversible lo más tarde posible. Cobrar, enviar un correo, disparar algo a un tercero.
  3. Un único punto de no retorno. Que exista un paso claro después del cual el flujo se considera hecho, y que todo lo anterior se pueda abandonar sin consecuencias.
  4. Lo que no se puede deshacer, que quede pendiente. En vez de enviar el correo en el medio, encolarlo para después de la confirmación.

Reintentar sin duplicar

Si un flujo puede fallar, va a haber reintentos: del usuario, de la red o automáticos. La única forma de que el reintento no duplique efectos es que cada operación sea idempotente.

Antes de seguir, predecí

Un usuario aprieta «pagar» dos veces porque la primera pareció no responder. ¿Qué evita el doble cobro?

Y ahí aparece un caso que confunde: si la respuesta se pierde en el camino, el cliente no sabe si la operación ocurrió. Por eso la consulta de estado es tan importante como la operación: permite preguntar en vez de reintentar a ciegas.

Cuando hay que deshacer

Cuando algo irreversible ya pasó y el flujo falla, no queda deshacer sino compensar: una operación nueva que revierte el efecto —liberar la reserva, devolver el cupón, emitir una nota de crédito—.

Tres condiciones para que la compensación sirva

  1. Que exista y esté escrita, no improvisada el día del incidente.
  2. Que sea idempotente también, porque va a correr en un contexto ya inestable.
  3. Que deje rastro, para que soporte pueda explicar qué pasó cuando el usuario llame.
Más a fondo · nivel seniorEsto es una saga, aunque nadie la llame así

El patrón formal se llama saga: una secuencia de pasos locales, cada uno con su compensación, que reemplaza a la transacción distribuida. Lo importante no es el nombre sino la consecuencia de diseño: si el flujo cruza más de un servicio, la atomicidad no existe y hay que elegir entre consistencia eventual con compensaciones o rediseñar para que lo crítico ocurra en un solo lugar. La segunda opción se considera menos de lo que debería.

El flujo que falla en el tercer paso

El flujo: validar, reservar stock, cobrar, confirmar. Todavía no pasó nada en el mundo.

1 / 7
La columna de la derecha es la que nadie escribe hasta que pasa. Fijate que no todos los efectos se pueden deshacer igual: la reserva se libera, el cupón se devuelve, y el correo ya no se puede desenviar. Ese último obliga a decidir el orden de los pasos, no a escribir una compensación.

Cómo se diseña un flujo que puede fallar

Cierre

Autoevaluación

¿Lo entendiste?

¿Por qué conviene dejar las operaciones irreversibles para el final del flujo?
¿Qué garantiza que un reintento no duplique un cobro?