| import time |
| from typing import Any, cast |
|
|
| import httpx |
|
|
| from src.server.config.logfire_config import get_logger |
|
|
| logger = get_logger(__name__) |
|
|
|
|
| class OllamaNetworkScanner: |
| """Handles network communication with Ollama instances.""" |
|
|
| def __init__(self, timeout: int = 30): |
| self.timeout = timeout |
|
|
| async def fetch_tags(self, instance_url: str) -> dict[str, Any]: |
| """Fetches the raw JSON response from the /api/tags endpoint.""" |
| async with httpx.AsyncClient(timeout=httpx.Timeout(self.timeout)) as client: |
| base_url = instance_url.rstrip("/").replace("/v1", "") |
| tags_url = f"{base_url}/api/tags" |
| response = await client.get(tags_url) |
| response.raise_for_status() |
| return cast(dict[str, Any], response.json()) |
|
|
| async def ping_health(self, instance_url: str) -> tuple[bool, float, int, str]: |
| """Pings the instance to check health. Returns (is_healthy, response_time_ms, models_count, error_message)""" |
| start_time = time.time() |
| try: |
| async with httpx.AsyncClient(timeout=httpx.Timeout(10)) as client: |
| ping_url = f"{instance_url.rstrip('/')}/api/tags" |
| response = await client.get(ping_url) |
| response.raise_for_status() |
| data = response.json() |
| models_count = len(data.get("models", [])) |
| response_time_ms = (time.time() - start_time) * 1000 |
| return True, response_time_ms, models_count, "" |
| except httpx.TimeoutException: |
| return False, 0.0, 0, "Connection timeout" |
| except httpx.HTTPStatusError as e: |
| return False, 0.0, 0, f"HTTP {e.response.status_code}" |
| except Exception as e: |
| return False, 0.0, 0, str(e) |
|
|