From 9f325a3c05d1b7d0e08dced0cb9faf6f58f4ebea Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 16 Sep 2026 04:00:08 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20la=20granja=20mol=C3=ADa=20UNA?= =?UTF-8?q?=20receta=20por=20cola=20y=20por=20ciclo=20=E2=80=94=20el=20`xa?= =?UTF-8?q?rgs=20-I{}`=20recib=C3=ADa=20la=20cola=20entera=20junta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Medido hoy al encolar `lld21` junto a `rust`: el ciclo decía «2 recetas en recipes/incoming» y construía UNA. La causa está en el filtro de «ya sellado en el hub»: acumula en `filtrada` uniendo con ESPACIOS, y más abajo la cola se le pasa a `xargs -I{}`, que trata **una línea = un elemento**. Unidas por espacios, N recetas llegan como UN SOLO argumento: printf '%s\n' " a.toml b.toml c.toml" | xargs -I{} sh -c 'echo [$1]' _ {} recibe: [a.toml b.toml c.toml] ← uno solo ⇒ la fase paralela fallaba SIEMPRE con «No such file», y la fase 1b —el reintento serial— salvaba exactamente UNA receta: la última, porque `basename` de esa ristra da el último nombre. El log parecía normal, con su ✗ seguido de un ✓ (reintento serial), y ese patrón está en TODAS las colas (yambar, spidermonkey, rust…). O sea que el reintento serial, que existe para conciliar colisiones de concurrencia, venía tapando el bug desde que se escribió el filtro. El arreglo son dos líneas: acumular con salto de línea y descartar la línea vacía con la que arranca el acumulador (una línea vacía también es un elemento para `xargs -I{}`). Probado en chiquito, en los dos sentidos: antes 1 elemento, después 3. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/build-farm.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/build-farm.sh b/scripts/build-farm.sh index d60712d0..3e7ad811 100755 --- a/scripts/build-farm.sh +++ b/scripts/build-farm.sh @@ -68,14 +68,26 @@ if [ -s "$SELLADOS" ]; then [ -n "$n" ] || n=$(basename "$f" .toml) H=$("$HAMMER" --store "$STORE" hash "$f" 2>/dev/null | tail -1 | sed 's/^b3://') if [ -n "$H" ] && grep -qx "$H-$n" "$SELLADOS"; then saltadas=$((saltadas+1)); continue; fi - filtrada="$filtrada $f" + # ⚠ SALTO DE LÍNEA Y NO ESPACIO, y esto era un BUG que costó throughput en silencio + # (medido 2026-09-16): más abajo la cola se le pasa a `xargs -I{}`, que trata **una línea = un + # elemento**. Unidas por espacios, N recetas llegaban como UN SOLO argumento: la fase paralela + # fallaba siempre con «No such file» y la fase 1b —el reintento serial— salvaba EXACTAMENTE UNA, + # la última, porque `basename` de esa ristra da el último nombre. O sea que la granja molía + # **una receta por cola y por ciclo** en vez de la cola entera, y el log parecía normal: un ✗ + # seguido de un ✓ (reintento serial). Se vio al encolar `lld21` junto a `rust` y descubrir que + # el ciclo decía «2 recetas» y construía una. + filtrada="$filtrada +$f" done [ "$cerradas" -gt 0 ] && echo " ($cerradas CERRADAS por decisión — ver la cabecera de cada receta)" [ "$saltadas" -gt 0 ] && echo " (saltadas $saltadas ya selladas en el hub — ver la nota del sync unidireccional)" queue="$filtrada" [ -n "$(echo $queue)" ] || { echo "nada que hacer en $QUEUE: todo sellado en el hub"; exit 0; } fi -n_total=$(printf '%s\n' "$queue" | wc -l | tr -d ' ') +# `grep -v` porque el acumulador del filtro arranca con una línea vacía, y una línea vacía es un +# elemento más para `xargs -I{}`: construiría la receta "" y ensuciaría el conteo. +queue=$(printf '%s\n' "$queue" | grep -v '^[[:space:]]*$' || true) +n_total=$(printf '%s\n' "$queue" | grep -c . || true) echo "==> GRANJA: $n_total recetas en $QUEUE, $JOBS workers en paralelo" # ── Fase 1: BUILD en paralelo. Cada worker construye una receta y deja su status (.ok con hash | .fail