Improve the dahboard with the weather info 2
This commit is contained in:
89
services/external/app/external/base_client.py
vendored
89
services/external/app/external/base_client.py
vendored
@@ -15,44 +15,61 @@ class BaseAPIClient:
|
||||
def __init__(self, base_url: str, api_key: Optional[str] = None):
|
||||
self.base_url = base_url
|
||||
self.api_key = api_key
|
||||
self.timeout = httpx.Timeout(30.0)
|
||||
# Increase timeout and add connection retries for unstable AEMET API
|
||||
self.timeout = httpx.Timeout(60.0) # Increased from 30s
|
||||
self.retries = 3
|
||||
|
||||
async def _get(self, endpoint: str, params: Optional[Dict] = None, headers: Optional[Dict] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Make GET request"""
|
||||
try:
|
||||
url = f"{self.base_url}{endpoint}"
|
||||
|
||||
# Add API key to params for AEMET (not headers)
|
||||
request_params = params or {}
|
||||
if self.api_key:
|
||||
request_params["api_key"] = self.api_key
|
||||
|
||||
# Add headers if provided
|
||||
request_headers = headers or {}
|
||||
|
||||
logger.debug("Making API request", url=url, params=request_params)
|
||||
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(url, params=request_params, headers=request_headers)
|
||||
response.raise_for_status()
|
||||
|
||||
# Log response for debugging
|
||||
response_data = response.json()
|
||||
logger.debug("API response received",
|
||||
status_code=response.status_code,
|
||||
response_keys=list(response_data.keys()) if isinstance(response_data, dict) else "non-dict")
|
||||
|
||||
return response_data
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error("HTTP error", status_code=e.response.status_code, url=url, response_text=e.response.text[:200])
|
||||
return None
|
||||
except httpx.RequestError as e:
|
||||
logger.error("Request error", error=str(e), url=url)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error("Unexpected error", error=str(e), url=url)
|
||||
return None
|
||||
"""Make GET request with retry logic for unstable APIs"""
|
||||
url = f"{self.base_url}{endpoint}"
|
||||
|
||||
# Add API key to params for AEMET (not headers)
|
||||
request_params = params or {}
|
||||
if self.api_key:
|
||||
request_params["api_key"] = self.api_key
|
||||
|
||||
# Add headers if provided
|
||||
request_headers = headers or {}
|
||||
|
||||
logger.debug("Making API request", url=url, params=request_params)
|
||||
|
||||
# Retry logic for unstable AEMET API
|
||||
for attempt in range(self.retries):
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=self.timeout) as client:
|
||||
response = await client.get(url, params=request_params, headers=request_headers)
|
||||
response.raise_for_status()
|
||||
|
||||
# Log response for debugging
|
||||
response_data = response.json()
|
||||
logger.debug("API response received",
|
||||
status_code=response.status_code,
|
||||
response_keys=list(response_data.keys()) if isinstance(response_data, dict) else "non-dict",
|
||||
attempt=attempt + 1)
|
||||
|
||||
return response_data
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error("HTTP error", status_code=e.response.status_code, url=url,
|
||||
response_text=e.response.text[:200], attempt=attempt + 1)
|
||||
if attempt == self.retries - 1: # Last attempt
|
||||
return None
|
||||
except httpx.RequestError as e:
|
||||
logger.error("Request error", error=str(e), url=url, attempt=attempt + 1)
|
||||
if attempt == self.retries - 1: # Last attempt
|
||||
return None
|
||||
|
||||
# Wait before retry (exponential backoff)
|
||||
import asyncio
|
||||
wait_time = 2 ** attempt # 1s, 2s, 4s
|
||||
logger.info(f"Retrying AEMET API in {wait_time}s", attempt=attempt + 1, max_attempts=self.retries)
|
||||
await asyncio.sleep(wait_time)
|
||||
except Exception as e:
|
||||
logger.error("Unexpected error", error=str(e), url=url, attempt=attempt + 1)
|
||||
if attempt == self.retries - 1: # Last attempt
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
async def _fetch_url_directly(self, url: str, headers: Optional[Dict] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Fetch data directly from a full URL (for AEMET datos URLs)"""
|
||||
|
||||
Reference in New Issue
Block a user