This commit is contained in:
2026-03-01 07:21:46 +01:00
parent 9db5cbf236
commit 7967f63fea
39 changed files with 3297 additions and 1646 deletions

View File

@@ -90,6 +90,70 @@ def _store_open_meteo() -> None:
logger.info(f"Open-Meteo stocké : {len(rows)} jours")
def backfill_station_missing_dates(max_days_back: int = 365) -> None:
"""Remplit les dates manquantes de la station météo au démarrage.
Cherche toutes les dates sans entrée « veille » dans meteostation
depuis max_days_back jours en arrière jusqu'à hier (excl. aujourd'hui),
puis télécharge les fichiers NOAA mois par mois pour remplir les trous.
Un seul appel HTTP par mois manquant.
"""
from datetime import date, timedelta
from itertools import groupby
from app.services.station import fetch_month_summaries
from app.models.meteo import MeteoStation
from app.database import engine
from sqlmodel import Session, select
today = date.today()
start_date = today - timedelta(days=max_days_back)
# 1. Dates « veille » déjà présentes en BDD
with Session(engine) as session:
rows = session.exec(
select(MeteoStation.date_heure).where(MeteoStation.type == "veille")
).all()
existing_dates: set[str] = {dh[:10] for dh in rows}
# 2. Dates manquantes entre start_date et hier (aujourd'hui exclu)
missing: list[date] = []
cursor = start_date
while cursor < today:
if cursor.isoformat() not in existing_dates:
missing.append(cursor)
cursor += timedelta(days=1)
if not missing:
logger.info("Backfill station : aucune date manquante")
return
logger.info(f"Backfill station : {len(missing)} date(s) manquante(s) à récupérer")
# 3. Grouper par (année, mois) → 1 requête HTTP par mois
def month_key(d: date) -> tuple[int, int]:
return (d.year, d.month)
filled = 0
for (year, month), group_iter in groupby(sorted(missing), key=month_key):
month_data = fetch_month_summaries(year, month)
if not month_data:
logger.debug(f"Backfill station : pas de données NOAA pour {year}-{month:02d}")
continue
with Session(engine) as session:
for d in group_iter:
data = month_data.get(d.day)
if not data:
continue
date_heure = f"{d.isoformat()}T00:00"
if not session.get(MeteoStation, date_heure):
session.add(MeteoStation(date_heure=date_heure, type="veille", **data))
filled += 1
session.commit()
logger.info(f"Backfill station terminé : {filled} date(s) insérée(s)")
def setup_scheduler() -> None:
"""Configure et démarre le scheduler."""
scheduler.add_job(