granja: guardián de disco en campana-deuda — corta en vez de anotar ✗ falsos
La cascada KDE del 2026-09-03 llenó el disco en la receta 52 de 71 y siguió moliendo: las 8 últimas murieron en 1-20 s con «No space left on device» y el bucle las anotó ✗, el mismo símbolo que una receta que no compila. El grafo del día siguiente decía «8 en deuda, clase c» y mandó a buscar un bug inexistente. Mide el MÍNIMO de dos filesystems, no uno: en gioser store/ (/dev/sdb, 109 G) y work/ (/dev/sdc, 53 G) son discos distintos y el que se llenó fue el de work/, donde vive el árbol de fuentes. Mirando sólo el store el vigía habría leído 109 G y dejado moler igual. Al cruzar el suelo corta con exit 3 y lista las recetas SIN INTENTAR, que no es lo mismo que fallidas.
This commit is contained in:
@@ -72,12 +72,47 @@ echo "$(ts) campaña-deuda: lock de build tomado (el worker-loop espera su turno
|
||||
total=$(echo "$DEUDA" | wc -w); i=0; ok=0; fail=0; falladas=""
|
||||
echo "$(ts) campaña-deuda arranca: $total recetas | go=$(command -v go || echo AUSENTE)" | tee -a "$LOG"
|
||||
|
||||
# ── GUARDIÁN DE DISCO (2026-09-04) ──────────────────────────────────────────────────────────────
|
||||
# POR QUÉ. La cascada KDE del 2026-09-03 llenó el disco en la receta 52 de 71 y siguió moliendo: las
|
||||
# 8 restantes murieron cada una en 1-20 s con `error in backend: IO failure on output stream: No
|
||||
# space left on device`, y el bucle las anotó `✗` — el MISMO símbolo que una receta que de verdad no
|
||||
# compila. Al día siguiente el grafo decía «8 en deuda, clase c» y eso mandó a leer recetas durante
|
||||
# un rato buscando un bug que no existía. Un disco lleno no es un fallo de receta: es un fallo de la
|
||||
# MÁQUINA, y confundirlos cuesta el triaje entero.
|
||||
#
|
||||
# Además el trabajo posterior al corte es puro desperdicio: 4 minutos quemados produciendo ✗.
|
||||
#
|
||||
# DÓNDE SE MIDE: en DOS filesystems, no en uno. En gioser `store/` y `work/` son discos DISTINTOS
|
||||
# (`/dev/sdb` el store, `/dev/sdc` el resto del repo) y el que se llenó esa noche fue el de `work/`:
|
||||
# ahí viven `work/sources/<receta>-<sha>` y el árbol de build, que es lo que crece ~300 MB por
|
||||
# receta. Un guardián que mirara sólo el store habría leído 109 G libres y dejado moler igual —
|
||||
# el fallo clásico de calibrar el vigía en una escala que el dato nunca alcanza. Se toma el MÍNIMO
|
||||
# de los dos: cualquiera de los dos lleno mata el build igual.
|
||||
#
|
||||
# Suelo en GiB. 8 G es ~1,5 veces el árbol+build de la receta más gorda que vimos (kwin, qt6); por
|
||||
# debajo de eso el siguiente build es una apuesta, no una tarea.
|
||||
SUELO_GIB="${SUELO_GIB:-8}"
|
||||
avail_gib() { df -B1G --output=avail "$1" 2>/dev/null | tail -1 | tr -d ' '; }
|
||||
libres_gib() {
|
||||
a="$(avail_gib "$STORE")"; b="$(avail_gib "$HAMMER_DIR/work")"
|
||||
[ -n "$a" ] || { echo "$b"; return; }
|
||||
[ -n "$b" ] || { echo "$a"; return; }
|
||||
[ "$a" -le "$b" ] && echo "$a" || echo "$b"
|
||||
}
|
||||
|
||||
for r in $DEUDA; do
|
||||
i=$((i + 1))
|
||||
f="recipes/$r.toml"
|
||||
[ -r "$f" ] || f="$(ls recipes/incoming*/"$r".toml 2>/dev/null | head -1)"
|
||||
[ -n "$f" ] && [ -r "$f" ] || { echo "$(ts) [$i/$total] $r ⚠ sin receta" | tee -a "$LOG"; continue; }
|
||||
echo "$(ts) [$i/$total] → $r" | tee -a "$LOG"
|
||||
libres="$(libres_gib)"
|
||||
if [ -n "$libres" ] && [ "$libres" -lt "$SUELO_GIB" ]; then
|
||||
echo "$(ts) [$i/$total] ⛔ DISCO: ${libres} G libres (min de store=$(avail_gib "$STORE") y work=$(avail_gib "$HAMMER_DIR/work")) < suelo ${SUELO_GIB} G ⇒ corto la campaña" | tee -a "$LOG"
|
||||
echo "$(ts) campaña-deuda ABORTADA por disco: $ok selladas, $fail fallidas, $((total - i + 1)) SIN INTENTAR" | tee -a "$LOG"
|
||||
echo "$(ts) sin intentar: $(echo "$DEUDA" | tr ' ' '\n' | tail -n +"$i" | tr '\n' ' ')" | tee -a "$LOG"
|
||||
exit 3
|
||||
fi
|
||||
# heartbeat: el dead-man ya cuenta `hammer build` como trabajo, pero entre receta y receta hay
|
||||
# huecos (fetch/vendor) donde no hay proceso con ese nombre. Tocarlo evita una muerte espuria.
|
||||
touch /run/hammer-heartbeat 2>/dev/null || true
|
||||
|
||||
Reference in New Issue
Block a user