import asyncio import logging from typing import Any, Optional import httpx from core.config import settings logger = logging.getLogger(__name__) class WorkspaceProfileClient: """Cliente para consultar perfil del usuario en Workspace Hub (/v1/auth/me).""" def __init__( self, base_url: Optional[str] = None, timeout_ms: Optional[int] = None, retries: int = 2, transport: Optional[httpx.BaseTransport] = None, ): self.base_url = (base_url or settings.hub_api_base_url).rstrip("/") self.timeout_s = max(0.1, float(timeout_ms or settings.HUB_PROFILE_SYNC_TIMEOUT_MS) / 1000.0) self.retries = max(0, int(retries)) self.transport = transport async def get_me(self, access_token: str) -> dict[str, Any]: if not access_token: raise ValueError("access_token is required") headers = {"Authorization": f"Bearer {access_token}"} url = f"{self.base_url}/v1/auth/me" last_error: Optional[Exception] = None for attempt in range(self.retries + 1): try: async with httpx.AsyncClient( timeout=self.timeout_s, transport=self.transport, ) as client: response = await client.get(url, headers=headers) if response.status_code == 200: payload = response.json() if not isinstance(payload, dict): raise ValueError("Invalid workspace profile payload") return payload if response.status_code in (401, 403, 404): # Errores de autenticación/autorización o endpoint no disponible: # no vale la pena reintentar. raise httpx.HTTPStatusError( f"Workspace profile request failed with status {response.status_code}", request=response.request, response=response, ) # Reintentar solo para errores transitorios 5xx. if response.status_code >= 500 and attempt < self.retries: await asyncio.sleep(0.15 * (attempt + 1)) continue raise httpx.HTTPStatusError( f"Workspace profile request failed with status {response.status_code}", request=response.request, response=response, ) except (httpx.TimeoutException, httpx.NetworkError) as exc: last_error = exc if attempt >= self.retries: break await asyncio.sleep(0.15 * (attempt + 1)) except Exception as exc: last_error = exc break if last_error: raise last_error raise RuntimeError("Workspace profile request failed")