ADR 0012: registrar como PENDIENTE el dilema del árbol de fuentes (caché vs workspace)

Queda una carrera abierta que el lock de script NO cierra: `build-farm.sh` corre `xargs -P2` y dos
recetas de la misma cola que compartan dep se pisan igual, porque `fetch` nombra el árbol de forma
determinista y sin nada del constructor.

El fondo no es "falta un lock", es que el árbol cumple DOS papeles que se contradicen bajo
concurrencia: caché direccionada por contenido (clave = nombre+sha, re-extraer es caro) y workspace
mutable de build (lib.rs lo parchea, aísla el workspace Cargo y vendorea EN EL SITIO, y después el
sandbox lo bind-montea). Por eso un lock alrededor de la extracción parece correcto y NO lo es: un
segundo proceso puede borrar un árbol que un bwrap ya está compilando.

El ADR deja las tres salidas (lock por árbol durante todo el build / árbol privado por build /
separar caché inmutable + copia privada) con su contra concreta cada una —incluida que el worker
corre ext4, sin reflink, así que la copia de la opción C es real— y los tres números que habría que
medir para elegir en vez de opinar.

Se ancla en los dos sitios donde alguien va a chocar: el ADR indexado en docs/README.md (de paso se
agregan 0009-0011, que faltaban) y un comentario en el propio `fetch_tarball` que dice explícitamente
que no se arregle a medias.

Va como PENDIENTE y no decidido a propósito: hay otro agente sobre este repo y esto es lo que evita
que la carrera se "arregle" de una forma que parece bien y deja el bug.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-22 17:34:50 -04:00
co-authored by Claude Opus 4.8
parent 062ae142aa
commit c963b24b5e
3 changed files with 104 additions and 0 deletions
+10
View File
@@ -114,6 +114,16 @@ fn fetch_tarball(
verify_sha256(&cached, sha256)?;
}
// ⚠ CARRERA CONOCIDA, SIN RESOLVER — ver docs/adr/0012-arbol-de-fuentes-compartido-vs-privado.md
// El path es determinista y NO lleva nada del constructor ⇒ dos builds de la misma receta (la
// misma dep alcanzada por dos caminos) resuelven al mismo directorio: uno borra mientras el otro
// extrae y el árbol queda roto con "Directory not empty" (os error 39) hasta borrarlo a mano.
// Mitigado SÓLO entre campana-deuda.sh y farm-worker-loop.sh con un lock de script (commit
// 1b436a7); el `xargs -P2` de build-farm.sh sigue expuesto.
// NO "arreglar" con un lock alrededor de esta extracción: parece correcto y no lo es, porque un
// segundo proceso puede borrar un árbol que un bwrap ya está usando para compilar. Este árbol es
// caché y workspace mutable a la vez (lib.rs lo parchea y vendorea in situ); el ADR 0012 plantea
// las tres salidas y qué medir para elegir.
let work_tree = sources_dir.join(format!("{}-{}", recipe.name, &sha256[..16]));
if work_tree.is_dir() {
std::fs::remove_dir_all(&work_tree)?;