Report TTS WordPress read failures instead of false zero backlog
This commit is contained in:
Regular → Executable
+52
-29
@@ -39,18 +39,21 @@ AUTORES = {
|
|||||||
386: ("Arregi", "ArregiFeadulta2026"),
|
386: ("Arregi", "ArregiFeadulta2026"),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Autor y rango que está locutando el cron ahora mismo (los valores por defecto
|
# Autor y rango que está locutando el cron ahora mismo. Debe seguir el crontab:
|
||||||
# de tts_backlog_cron.sh). Solo afecta a qué línea se marca como "en curso".
|
# solo afecta a qué línea se marca como «en curso» en el informe diario.
|
||||||
ACTIVO = (382, 2025, 2026)
|
ACTIVO = (774, 2000, 2026)
|
||||||
|
|
||||||
|
|
||||||
def php(*args: str) -> str:
|
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(
|
r = subprocess.run(
|
||||||
["docker", "exec", CONTAINER, "php", "/tmp/fea_post_io.php", *args],
|
["docker", "exec", CONTAINER, "php", "/tmp/fea_post_io.php", *args],
|
||||||
capture_output=True, text=True,
|
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:
|
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:
|
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
|
El backlog usa varias líneas de crontab (ritmo normal + sábado + domingo).
|
||||||
daba la alarma de 'ninguna ventana dejó rastro' estando todo correcto. La
|
Se calcula la unión de sus instantes previstos, sin contar dos veces una
|
||||||
verdad está en el crontab, no aquí: si Rafa cambia los días, esto le sigue.
|
coincidencia entre líneas.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
linea = next(
|
lineas = [
|
||||||
l for l in subprocess.run(["crontab", "-l"], text=True, capture_output=True,
|
l for l in subprocess.run(["crontab", "-l"], text=True, capture_output=True,
|
||||||
check=True).stdout.splitlines()
|
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
|
except Exception: # noqa: BLE001
|
||||||
return None
|
return None
|
||||||
campos = linea.split(None, 5)
|
if not lineas:
|
||||||
if len(campos) < 5:
|
|
||||||
return None
|
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()
|
ahora = ahora or datetime.now()
|
||||||
n = 0
|
inicio = ahora - timedelta(hours=24)
|
||||||
for h in range(25):
|
previstos: set[datetime] = set()
|
||||||
t = (ahora - timedelta(hours=h)).replace(second=0, microsecond=0)
|
for linea in lineas:
|
||||||
for m in minutos:
|
campos = linea.split(None, 5)
|
||||||
cand = t.replace(minute=m)
|
if len(campos) < 5:
|
||||||
if not (ahora - timedelta(hours=24) < cand <= ahora):
|
continue
|
||||||
continue
|
try:
|
||||||
if cand.hour in horas and (cand.weekday() + 1) % 7 in dows:
|
minutos = _campo_cron(campos[0], range(60))
|
||||||
n += 1
|
horas = _campo_cron(campos[1], range(24))
|
||||||
return n
|
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:
|
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())
|
total = sum(len(v) for v in hechos.values())
|
||||||
corridas, saltadas, fallos = logs_24h()
|
corridas, saltadas, fallos = logs_24h()
|
||||||
p5, pw = cuota()
|
p5, pw = cuota()
|
||||||
@@ -194,10 +218,9 @@ def main() -> int:
|
|||||||
lineas.append("")
|
lineas.append("")
|
||||||
lineas.append("Pendientes:")
|
lineas.append("Pendientes:")
|
||||||
for aid, (nombre, voz) in AUTORES.items():
|
for aid, (nombre, voz) in AUTORES.items():
|
||||||
falta_todo = pendientes(aid, 0, 9999, voz)
|
falta_todo, falta_lote = faltantes[aid]
|
||||||
marca = ""
|
marca = ""
|
||||||
if aid == ACTIVO[0]:
|
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]}"
|
marca = f" ← en curso, {falta_lote} del lote {ACTIVO[1]}-{ACTIVO[2]}"
|
||||||
lineas.append(f" {nombre}: {falta_todo}{marca}")
|
lineas.append(f" {nombre}: {falta_todo}{marca}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user