Migra el servicio a arquitectura Docker persistente y mueve credenciales HANA a .env
- Reemplaza config_loader/config_model/hana_client/logger_utilities/outlook_utilities por core.py (pipeline funcional), hana_manager.py, logger_manager.py, scheduler.py y descargador_sovos.py (Playwright/Firefox) según la plantilla de servicios. - main.py pasa a loop continuo dirigido por scheduler.json, con manejo de SIGINT/SIGTERM. - Agrega Dockerfile, docker-compose.yml (restart unless-stopped) y certs/ para despliegue. - Agrega smb_transfer.py para la transferencia a carpeta compartida. - Saca las credenciales de HANA de config.json y las mueve a .env (HANA_HOST/PORT/USER/PASSWORD).
This commit is contained in:
1 parent
1503d6a2ec
commit
277d07dfeb
22 files changed
+1081
-750
No files matched your search
@@ -0,0 +1,61 @@
|
||||
"""scheduler.py — franja horaria activa para el while loop de main.py.
|
||||
|
||||
Lee scheduler.json (HORARIOS + DIAS_ACTIVOS) y responde dos preguntas:
|
||||
* franja_actual(): si ahora cae dentro de una franja, con qué modo.
|
||||
* proximo_inicio(): si no, cuándo empieza la próxima franja activa.
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# ============================================================================
|
||||
SCHEDULER_FILE = Path(__file__).parent / "scheduler.json"
|
||||
|
||||
INTERVALOS_POR_MODO = {
|
||||
"rapido": 10 * 60,
|
||||
"full": 60 * 60,
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
def cargar_scheduler(path: Path | None = None) -> dict:
|
||||
p = path or SCHEDULER_FILE
|
||||
with open(p, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def _minutos(hora: int, minuto: int) -> int:
|
||||
return hora * 60 + minuto
|
||||
|
||||
|
||||
def franja_actual(cfg: dict, ahora: datetime) -> dict | None:
|
||||
if ahora.weekday() not in cfg.get("DIAS_ACTIVOS", []):
|
||||
return None
|
||||
|
||||
minutos_ahora = _minutos(ahora.hour, ahora.minute)
|
||||
for h_ini, m_ini, h_fin, m_fin, modo in cfg.get("HORARIOS", []):
|
||||
if _minutos(h_ini, m_ini) <= minutos_ahora < _minutos(h_fin, m_fin):
|
||||
return {"modo": modo, "intervalo": INTERVALOS_POR_MODO.get(modo, 600)}
|
||||
return None
|
||||
|
||||
|
||||
def proximo_inicio(cfg: dict, ahora: datetime) -> datetime:
|
||||
dias_activos = cfg.get("DIAS_ACTIVOS", [])
|
||||
horarios = cfg.get("HORARIOS", [])
|
||||
if not dias_activos or not horarios:
|
||||
raise ValueError("scheduler.json sin DIAS_ACTIVOS o HORARIOS configurados")
|
||||
|
||||
for delta in range(0, 8):
|
||||
candidato = ahora + timedelta(days=delta)
|
||||
if candidato.weekday() not in dias_activos:
|
||||
continue
|
||||
inicios = []
|
||||
for h_ini, m_ini, h_fin, m_fin, _modo in horarios:
|
||||
inicio = candidato.replace(hour=h_ini, minute=m_ini, second=0, microsecond=0)
|
||||
if delta == 0 and inicio <= ahora:
|
||||
continue
|
||||
inicios.append(inicio)
|
||||
if inicios:
|
||||
return min(inicios)
|
||||
|
||||
raise ValueError("No se encontró una próxima franja activa en los próximos 7 días")
|
||||
# ============================================================================
|
||||
Reference in new issue
Block a user