- 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).
57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
"""main.py — entrada delgada. Bucle continuo dirigido por scheduler.json."""
|
|
import signal
|
|
import time
|
|
from datetime import datetime
|
|
|
|
from core import ejecutar
|
|
from scheduler import cargar_scheduler, franja_actual, proximo_inicio
|
|
from logger_manager import get_logger
|
|
|
|
logger = get_logger("main")
|
|
|
|
_running = True
|
|
|
|
# ============================================================================
|
|
def _signal_handler(signum, frame):
|
|
global _running
|
|
logger.info("⏹️ Señal de parada recibida. Deteniendo tras el ciclo actual...")
|
|
_running = False
|
|
|
|
|
|
def _dormir_interrumpible(segundos: float):
|
|
"""Duerme en pasos de 1s para reaccionar rápido a SIGTERM/SIGINT."""
|
|
restante = int(segundos)
|
|
while restante > 0 and _running:
|
|
time.sleep(min(1, restante))
|
|
restante -= 1
|
|
|
|
# ============================================================================
|
|
if __name__ == "__main__":
|
|
signal.signal(signal.SIGINT, _signal_handler)
|
|
signal.signal(signal.SIGTERM, _signal_handler)
|
|
|
|
while _running:
|
|
try:
|
|
cfg_scheduler = cargar_scheduler()
|
|
ahora = datetime.now()
|
|
franja = franja_actual(cfg_scheduler, ahora)
|
|
|
|
if franja is None:
|
|
proximo = proximo_inicio(cfg_scheduler, ahora)
|
|
segundos = max((proximo - ahora).total_seconds(), 0)
|
|
logger.info(
|
|
f"⏸️ Fuera de horario. Próxima franja: {proximo:%Y-%m-%d %H:%M} "
|
|
f"(durmiendo {int(segundos)}s)"
|
|
)
|
|
_dormir_interrumpible(segundos)
|
|
continue
|
|
|
|
ejecutar()
|
|
_dormir_interrumpible(franja["intervalo"])
|
|
except Exception:
|
|
logger.error("Excepción no controlada en el ciclo", exc_info=True)
|
|
_dormir_interrumpible(60)
|
|
|
|
logger.info("👋 Proceso detenido.")
|
|
# ============================================================================
|