60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from app.config import RADAR_PRODUCT, RADAR_RETENTION_HOURS, RAW_RADAR_DIR
|
|
from app.database import upsert_radar_meta
|
|
from app.http_client import get_client
|
|
from app.services.dwd_radar import RADAR_FILE_RE, fetch_radar_index
|
|
|
|
_FILENAME_RE = re.compile(r"^[a-z0-9_-]+$", re.IGNORECASE)
|
|
|
|
|
|
def utc_now() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
def cleanup_old_radar_files() -> None:
|
|
cutoff = utc_now() - timedelta(hours=RADAR_RETENTION_HOURS)
|
|
if not RAW_RADAR_DIR.exists():
|
|
return
|
|
for path in RAW_RADAR_DIR.rglob("*"):
|
|
if not path.is_file() or not RADAR_FILE_RE.fullmatch(path.name):
|
|
continue
|
|
modified = datetime.fromtimestamp(path.stat().st_mtime, timezone.utc)
|
|
if modified < cutoff:
|
|
path.unlink(missing_ok=True)
|
|
|
|
|
|
async def sync_radar_files(product: str = RADAR_PRODUCT, limit: int = 6) -> dict:
|
|
if not _FILENAME_RE.fullmatch(product):
|
|
raise ValueError("Invalid product")
|
|
|
|
latest = await fetch_radar_index(product=product, limit=limit)
|
|
target_dir = RAW_RADAR_DIR / "composite" / product
|
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
downloaded: list[str] = []
|
|
skipped: list[str] = []
|
|
|
|
client = get_client()
|
|
for item in latest["files"]:
|
|
out = target_dir / item["name"]
|
|
if out.exists() and out.stat().st_size > 0:
|
|
skipped.append(item["name"])
|
|
continue
|
|
response = await client.get(item["url"], timeout=90.0)
|
|
response.raise_for_status()
|
|
out.write_bytes(response.content)
|
|
downloaded.append(item["name"])
|
|
modified = datetime.fromtimestamp(out.stat().st_mtime, timezone.utc)
|
|
await upsert_radar_meta(product, item["name"], out.stat().st_size, modified, "pending")
|
|
|
|
cleanup_old_radar_files()
|
|
return {
|
|
"product": product,
|
|
"target_dir": str(target_dir),
|
|
"downloaded": downloaded,
|
|
"skipped": skipped,
|
|
}
|