API

La API suele ser el primer lugar donde una petición entra al sistema y, por eso mismo, suele terminar cargando responsabilidades que no le corresponden. Cuando el handler valida reglas, escribe datos, publica eventos y traduce errores, ya no es una puerta: es toda la casa.

En una operación con reglas, api/ recibe la petición, llama al flow y, si hay cambios que persistir, guarda el resultado mediante fx/db. No contiene la regla del carrito: esa ya se aplicó antes de devolver el resultado. Una consulta o escritura técnica sin reglas puede llamar directamente a fx/; los distintos casos se muestran en Estructura.

let mut tx = state.db.begin().await?;

let cart = flows::cart::add_product(
    &mut tx,
    request.cart_id,
    request.product_id,
    request.quantity,
).await?;

fx::db::update_cart(&mut tx, &cart).await?;
tx.commit().await?;

La API abre la transacción, se la presta al flow para consultar, escribe el resultado y hace commit. El flow no guarda los datos.

Cuando una decisión depende de lo consultado, la consulta y la escritura deben mantenerse en esa misma transacción. Eso no evita por sí solo todos los conflictos entre peticiones: según la regla, harán falta bloqueos, restricciones o un nivel de aislamiento adecuado. Si la escritura falla, la API propaga el error y no confirma la transacción.

La misma función puede llamarse desde HTTP y desde gRPC:

HTTP  ──┐
        ├── flows::cart::add_product
gRPC ──┘

Cuando la operación ya terminó y hay que hablar con otro sistema, eso queda en la API. En un proyecto chico, en el handler. Cuando el handler se vuelve un guion difícil de leer, en api/actions/. El nombre no crea una nueva capa: solo da un lugar al guion que ya existe.

En el checkout del carrito complejo, el flow calcula y devuelve el pedido; API lo persiste y confirma la transacción. Confirmar el pago, descontar inventario en otro servicio y avisar al cliente son acciones posteriores. Si fallan, el pedido ya existe y el fallo queda registrado. No se meten dentro de checkout para que el flow «quede completo».