"""HTTP client for Tracker API.""" import logging from typing import Any, Optional import httpx from config import TRACKER_URL, TRACKER_TOKEN logger = logging.getLogger("bff.tracker") _client: Optional[httpx.AsyncClient] = None def get_client() -> httpx.AsyncClient: global _client if _client is None or _client.is_closed: _client = httpx.AsyncClient( base_url=TRACKER_URL, headers={"Authorization": f"Bearer {TRACKER_TOKEN}"}, timeout=30.0, ) return _client async def tracker_request(method: str, path: str, **kwargs) -> httpx.Response: client = get_client() logger.info("[TRACKER] %s %s", method, path) resp = await client.request(method, path, **kwargs) logger.info("[TRACKER] %s %s → %d", method, path, resp.status_code) return resp async def tracker_get(path: str, **kwargs) -> Any: resp = await tracker_request("GET", path, **kwargs) resp.raise_for_status() return resp.json() async def tracker_post(path: str, **kwargs) -> Any: resp = await tracker_request("POST", path, **kwargs) resp.raise_for_status() return resp.json() async def tracker_patch(path: str, **kwargs) -> Any: resp = await tracker_request("PATCH", path, **kwargs) resp.raise_for_status() return resp.json() async def tracker_delete(path: str, **kwargs) -> int: resp = await tracker_request("DELETE", path, **kwargs) resp.raise_for_status() return resp.status_code async def close_client(): global _client if _client and not _client.is_closed: await _client.aclose() _client = None