|
14 | 14 | class ServerHealthCheck: |
15 | 15 | """Health check for upstream API.""" |
16 | 16 |
|
17 | | - url: str | HttpUrl |
| 17 | + urls: list[str | HttpUrl] |
18 | 18 | max_retries: int = 5 |
19 | | - retry_delay: float = 0.25 |
| 19 | + retry_delay: float = 0.5 |
20 | 20 | retry_delay_max: float = 10.0 |
21 | 21 | timeout: float = 5.0 |
22 | 22 |
|
23 | 23 | def __post_init__(self): |
24 | 24 | """Convert url to string if it's a HttpUrl.""" |
25 | | - if isinstance(self.url, HttpUrl): |
26 | | - self.url = str(self.url) |
| 25 | + self.urls = [str(url) if isinstance(url, HttpUrl) else url for url in self.urls] |
27 | 26 |
|
28 | | - async def _check_health(self) -> bool: |
| 27 | + async def _check_health(self, url: str) -> bool: |
29 | 28 | """Check if upstream API is responding.""" |
30 | | - try: |
31 | | - async with httpx.AsyncClient() as client: |
32 | | - response = await client.get( |
33 | | - self.url, timeout=self.timeout, follow_redirects=True |
34 | | - ) |
35 | | - response.raise_for_status() |
36 | | - return True |
37 | | - except Exception as e: |
38 | | - logger.warning(f"Upstream health check for {self.url!r} failed: {e}") |
39 | | - return False |
40 | | - |
41 | | - async def __call__(self) -> None: |
42 | | - """Wait for upstream API to become available.""" |
43 | 29 | for attempt in range(self.max_retries): |
44 | | - if await self._check_health(): |
45 | | - logger.info(f"Upstream API {self.url!r} is healthy") |
46 | | - return |
| 30 | + try: |
| 31 | + async with httpx.AsyncClient() as client: |
| 32 | + response = await client.get( |
| 33 | + url, timeout=self.timeout, follow_redirects=True |
| 34 | + ) |
| 35 | + response.raise_for_status() |
| 36 | + logger.info(f"Upstream API {url!r} is healthy") |
| 37 | + return True |
| 38 | + except Exception as e: |
| 39 | + logger.warning(f"Upstream health check for {url!r} failed: {e}") |
47 | 40 |
|
48 | 41 | retry_in = min(self.retry_delay * (2**attempt), self.retry_delay_max) |
49 | 42 | logger.warning( |
50 | | - f"Upstream API {self.url!r} not healthy, retrying in {retry_in:.1f}s " |
| 43 | + f"Upstream API {url!r} not healthy, retrying in {retry_in:.1f}s " |
51 | 44 | f"(attempt {attempt + 1}/{self.max_retries})" |
52 | 45 | ) |
53 | 46 | await asyncio.sleep(retry_in) |
54 | 47 |
|
55 | 48 | raise RuntimeError( |
56 | | - f"Upstream API {self.url!r} failed to respond after {self.max_retries} attempts" |
| 49 | + f"Upstream API {url!r} failed to respond after {self.max_retries} attempts" |
57 | 50 | ) |
| 51 | + |
| 52 | + async def __call__(self) -> None: |
| 53 | + """Wait for upstream API to become available.""" |
| 54 | + for url in self.urls: |
| 55 | + await self._check_health(url) |
0 commit comments