Report TTS WordPress read failures instead of false zero backlog

This commit is contained in:
2026-08-28 04:20:15 -04:00
parent de91485854
commit bda4a753c9
+52 -29
View File
@@ -39,18 +39,21 @@ AUTORES = {
386: ("Arregi", "ArregiFeadulta2026"),
}
# Autor y rango que está locutando el cron ahora mismo (los valores por defecto
# de tts_backlog_cron.sh). Solo afecta a qué línea se marca como "en curso".
ACTIVO = (382, 2025, 2026)
# Autor y rango que está locutando el cron ahora mismo. Debe seguir el crontab:
# solo afecta a qué línea se marca como «en curso» en el informe diario.
ACTIVO = (774, 2000, 2026)
def php(*args: str) -> str:
"""fea_post_io.php dentro del contenedor. stderr fuera: WP escupe warnings."""
"""Llama al helper WP sin convertir un fallo de lectura en una cola vacía."""
r = subprocess.run(
["docker", "exec", CONTAINER, "php", "/tmp/fea_post_io.php", *args],
capture_output=True, text=True,
)
return r.stdout if r.returncode == 0 else ""
if r.returncode != 0:
detail = (r.stderr or r.stdout).strip().replace("\n", " ")[:300]
raise RuntimeError(f"consulta WP {' '.join(args)} falló (rc={r.returncode}): {detail}")
return r.stdout
def pendientes(autor: int, desde: int, hasta: int, voz: str) -> int:
@@ -143,41 +146,62 @@ def _campo_cron(campo: str, valores: range) -> set[int]:
def previstas_24h(ahora: datetime | None = None) -> int | None:
"""Cuántas ventanas TENÍA que haber corrido el cron en las últimas 24 h.
"""Cuántas ventanas tenían que haber corrido en las últimas 24 horas.
Sin esto, los martes/miércoles/jueves (días de carta, sin cron) el informe
daba la alarma de 'ninguna ventana dejó rastro' estando todo correcto. La
verdad está en el crontab, no aquí: si Rafa cambia los días, esto le sigue.
El backlog usa varias líneas de crontab (ritmo normal + sábado + domingo).
Se calcula la unión de sus instantes previstos, sin contar dos veces una
coincidencia entre líneas.
"""
try:
linea = next(
lineas = [
l for l in subprocess.run(["crontab", "-l"], text=True, capture_output=True,
check=True).stdout.splitlines()
if "tts_backlog_cron.sh" in l and not l.lstrip().startswith("#"))
if "tts_backlog_cron.sh" in l and not l.lstrip().startswith("#")
]
except Exception: # noqa: BLE001
return None
campos = linea.split(None, 5)
if len(campos) < 5:
if not lineas:
return None
minutos = _campo_cron(campos[0], range(60))
horas = _campo_cron(campos[1], range(24))
dows = {d % 7 for d in _campo_cron(campos[4], range(7))} # cron: 0 y 7 = domingo
ahora = ahora or datetime.now()
n = 0
for h in range(25):
t = (ahora - timedelta(hours=h)).replace(second=0, microsecond=0)
for m in minutos:
cand = t.replace(minute=m)
if not (ahora - timedelta(hours=24) < cand <= ahora):
continue
if cand.hour in horas and (cand.weekday() + 1) % 7 in dows:
n += 1
return n
inicio = ahora - timedelta(hours=24)
previstos: set[datetime] = set()
for linea in lineas:
campos = linea.split(None, 5)
if len(campos) < 5:
continue
try:
minutos = _campo_cron(campos[0], range(60))
horas = _campo_cron(campos[1], range(24))
dows = {d % 7 for d in _campo_cron(campos[4], range(7))}
except (TypeError, ValueError):
continue
for h in range(25):
t = (ahora - timedelta(hours=h)).replace(second=0, microsecond=0)
for m in minutos:
cand = t.replace(minute=m)
if inicio < cand <= ahora and cand.hour in horas and (cand.weekday() + 1) % 7 in dows:
previstos.add(cand)
return len(previstos)
def main() -> int:
hechos = hechos_24h()
# Nunca informar «0 pendientes» cuando la lectura de WordPress ha fallado.
# El cron no-agent entrega stdout/errores tal cual: un aviso explícito permite
# arreglar Docker/helper sin que parezca que el backlog está terminado.
try:
hechos = hechos_24h()
faltantes = {
aid: (pendientes(aid, 0, 9999, voz),
pendientes(aid, ACTIVO[1], ACTIVO[2], voz) if aid == ACTIVO[0] else None)
for aid, (_nombre, voz) in AUTORES.items()
}
except RuntimeError as exc:
print("⚠️ Fe Adulta — informe TTS inválido: no se pudo leer WordPress.")
print(f" {exc}")
print(" Los ceros no son datos reales; revisar wordpress-web y /tmp/fea_post_io.php.")
return 1
total = sum(len(v) for v in hechos.values())
corridas, saltadas, fallos = logs_24h()
p5, pw = cuota()
@@ -194,10 +218,9 @@ def main() -> int:
lineas.append("")
lineas.append("Pendientes:")
for aid, (nombre, voz) in AUTORES.items():
falta_todo = pendientes(aid, 0, 9999, voz)
falta_todo, falta_lote = faltantes[aid]
marca = ""
if aid == ACTIVO[0]:
falta_lote = pendientes(aid, ACTIVO[1], ACTIVO[2], voz)
marca = f" ← en curso, {falta_lote} del lote {ACTIVO[1]}-{ACTIVO[2]}"
lineas.append(f" {nombre}: {falta_todo}{marca}")