| 1492 | @pytest.mark.asyncio |
| 1493 | @pytest.mark.parametrize("failure_mode", ["status", "exception"]) |
| 1494 | async def test_retries_taken( |
| 1495 | self, |
| 1496 | async_client: AsyncOpencode, |
| 1497 | failures_before_success: int, |
| 1498 | failure_mode: Literal["status", "exception"], |
| 1499 | respx_mock: MockRouter, |
| 1500 | ) -> None: |
| 1501 | client = async_client.with_options(max_retries=4) |
| 1502 | |
| 1503 | nb_retries = 0 |
| 1504 | |
| 1505 | def retry_handler(_request: httpx.Request) -> httpx.Response: |
| 1506 | nonlocal nb_retries |
| 1507 | if nb_retries < failures_before_success: |
| 1508 | nb_retries += 1 |
| 1509 | if failure_mode == "exception": |
| 1510 | raise RuntimeError("oops") |
| 1511 | return httpx.Response(500) |
| 1512 | return httpx.Response(200) |
| 1513 | |
| 1514 | respx_mock.get("/session").mock(side_effect=retry_handler) |
| 1515 | |
| 1516 | response = await client.session.with_raw_response.list() |
| 1517 | |
| 1518 | assert response.retries_taken == failures_before_success |
| 1519 | assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success |
| 1520 | |
| 1521 | @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) |
| 1522 | @mock.patch("opencode_ai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) |