Report TTS WordPress read failures instead of false zero backlog
This commit is contained in:
Regular → Executable
+47
-24
@@ -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
|
||||
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 not (ahora - timedelta(hours=24) < cand <= ahora):
|
||||
continue
|
||||
if cand.hour in horas and (cand.weekday() + 1) % 7 in dows:
|
||||
n += 1
|
||||
return n
|
||||
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:
|
||||
# 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}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user