IT-Stock/app/scheduler.py

51 lines
2 KiB
Python
Raw Normal View History

"""
Planification de l'email récapitulatif de stock (voir
email_alerts.envoyer_resume_stock).
Choix : un planificateur qui tourne dans le process FastAPI lui-même
(APScheduler), configuré par une expression cron classique (RESUME_STOCK_CRON
dans .env, ex: "0 8 * * *" = tous les jours à 8h). Rien à configurer côté
système d'exploitation du serveur — tout reste dans ce dossier, comme le
reste du projet.
Limite à connaître : la tâche ne se déclenche que si le process est en
cours d'exécution au moment prévu, sans rattrapage si le serveur était
arrêté à ce moment-. Pour un outil interne redémarré rarement, c'est un
compromis raisonnable face à la complexité d'un vrai cron système. Si ça
devient un problème, scripts/envoyer_resume_stock.py peut être branché
sur un cron/Planificateur de tâches Windows à la place.
"""
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from sqlmodel import Session
from app.config import settings
from app.database import engine
from app.email_alerts import envoyer_resume_stock
_scheduler = BackgroundScheduler()
def _tache_resume_stock() -> None:
"""Ouvre sa propre session DB : cette fonction est appelée par le
thread du planificateur, en dehors du cycle requête/réponse FastAPI
la session habituelle (get_session) n'existe pas."""
with Session(engine) as session:
envoyer_resume_stock(session)
def demarrer_planification() -> None:
"""Démarre la tâche planifiée. Appelé une fois au démarrage de l'app
(voir lifespan dans main.py)."""
trigger = CronTrigger.from_crontab(settings.resume_stock_cron)
_scheduler.add_job(_tache_resume_stock, trigger, id="resume_stock", replace_existing=True)
if not _scheduler.running:
_scheduler.start()
def arreter_planification() -> None:
"""Arrête proprement le planificateur (appelé à l'extinction de l'app)."""
if _scheduler.running:
_scheduler.shutdown(wait=False)