from __future__ import annotations import asyncio import time from typing import Any from app.cache import cache_get, cache_set, redis_available from app.config import ( BRIGHTSKY_BASE_URL, CACHE_TTL_HEALTH_SOURCES, DATABASE_URL, DWD_RADAR_BASE_URL, DWD_WMS_URL, DWD_WARNINGS_URL, OPEN_METEO_BASE_URL, ) from app.database import pool_available from app.http_client import get_client async def _probe(name: str, url: str, timeout: float = 5.0) -> dict[str, Any]: started = time.perf_counter() try: client = get_client() response = await client.get(url, timeout=timeout) elapsed_ms = round((time.perf_counter() - started) * 1000, 1) ok = response.status_code < 500 return { "name": name, "url": url, "status": "ok" if ok else "degraded", "http_status": response.status_code, "latency_ms": elapsed_ms, } except Exception as exc: elapsed_ms = round((time.perf_counter() - started) * 1000, 1) return { "name": name, "url": url, "status": "error", "error": str(exc), "latency_ms": elapsed_ms, } async def check_sources() -> list[dict[str, Any]]: cache_key = "health:sources" cached = await cache_get(cache_key) if cached: return cached probes = await asyncio.gather( _probe("open_meteo", f"{OPEN_METEO_BASE_URL}/forecast?latitude=52.5&longitude=13.4¤t=temperature_2m"), _probe("brightsky", f"{BRIGHTSKY_BASE_URL}/current_weather?lat=52.5&lon=13.4"), _probe("dwd_radar", f"{DWD_RADAR_BASE_URL}/rv/", timeout=4.0), _probe("dwd_wms", f"{DWD_WMS_URL}?service=WMS&request=GetCapabilities", timeout=6.0), _probe("dwd_warnings", DWD_WARNINGS_URL, timeout=4.0), ) results = list(probes) results.append( { "name": "postgres", "url": DATABASE_URL.split("@")[-1], "status": "ok" if pool_available() else "disabled", } ) results.append( { "name": "redis", "url": "redis", "status": "ok" if redis_available() else "disabled", } ) await cache_set(cache_key, results, CACHE_TTL_HEALTH_SOURCES) return results