Skip to content

Commit f461957

Browse files
Cover HTTP 408 retries in pagination and wait helpers
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 4dfa26e commit f461957

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

tests/test_polling.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,31 @@ def get_next_page(page: int) -> dict:
14371437
assert attempts["count"] == 3
14381438

14391439

1440+
def test_collect_paginated_results_retries_request_timeout_errors():
1441+
attempts = {"count": 0}
1442+
collected = []
1443+
1444+
def get_next_page(page: int) -> dict:
1445+
attempts["count"] += 1
1446+
if attempts["count"] < 3:
1447+
raise HyperbrowserError("request timeout", status_code=408)
1448+
return {"current": 1, "total": 1, "items": ["a"]}
1449+
1450+
collect_paginated_results(
1451+
operation_name="sync paginated request-timeout retries",
1452+
get_next_page=get_next_page,
1453+
get_current_page_batch=lambda response: response["current"],
1454+
get_total_page_batches=lambda response: response["total"],
1455+
on_page_success=lambda response: collected.extend(response["items"]),
1456+
max_wait_seconds=1.0,
1457+
max_attempts=5,
1458+
retry_delay_seconds=0.0001,
1459+
)
1460+
1461+
assert collected == ["a"]
1462+
assert attempts["count"] == 3
1463+
1464+
14401465
def test_collect_paginated_results_raises_when_page_batch_stagnates():
14411466
with pytest.raises(HyperbrowserPollingError, match="No pagination progress"):
14421467
collect_paginated_results(
@@ -1709,6 +1734,34 @@ async def get_next_page(page: int) -> dict:
17091734
asyncio.run(run())
17101735

17111736

1737+
def test_collect_paginated_results_async_retries_request_timeout_errors():
1738+
async def run() -> None:
1739+
attempts = {"count": 0}
1740+
collected = []
1741+
1742+
async def get_next_page(page: int) -> dict:
1743+
attempts["count"] += 1
1744+
if attempts["count"] < 3:
1745+
raise HyperbrowserError("request timeout", status_code=408)
1746+
return {"current": 1, "total": 1, "items": ["a"]}
1747+
1748+
await collect_paginated_results_async(
1749+
operation_name="async paginated request-timeout retries",
1750+
get_next_page=get_next_page,
1751+
get_current_page_batch=lambda response: response["current"],
1752+
get_total_page_batches=lambda response: response["total"],
1753+
on_page_success=lambda response: collected.extend(response["items"]),
1754+
max_wait_seconds=1.0,
1755+
max_attempts=5,
1756+
retry_delay_seconds=0.0001,
1757+
)
1758+
1759+
assert collected == ["a"]
1760+
assert attempts["count"] == 3
1761+
1762+
asyncio.run(run())
1763+
1764+
17121765
def test_wait_for_job_result_returns_fetched_value():
17131766
status_values = iter(["running", "completed"])
17141767

@@ -1775,6 +1828,31 @@ def fetch_result() -> dict:
17751828
assert fetch_attempts["count"] == 3
17761829

17771830

1831+
def test_wait_for_job_result_retries_request_timeout_fetch_errors():
1832+
fetch_attempts = {"count": 0}
1833+
1834+
def fetch_result() -> dict:
1835+
fetch_attempts["count"] += 1
1836+
if fetch_attempts["count"] < 3:
1837+
raise HyperbrowserError("request timeout", status_code=408)
1838+
return {"ok": True}
1839+
1840+
result = wait_for_job_result(
1841+
operation_name="sync wait helper request-timeout retries",
1842+
get_status=lambda: "completed",
1843+
is_terminal_status=lambda value: value == "completed",
1844+
fetch_result=fetch_result,
1845+
poll_interval_seconds=0.0001,
1846+
max_wait_seconds=1.0,
1847+
max_status_failures=2,
1848+
fetch_max_attempts=5,
1849+
fetch_retry_delay_seconds=0.0001,
1850+
)
1851+
1852+
assert result == {"ok": True}
1853+
assert fetch_attempts["count"] == 3
1854+
1855+
17781856
def test_wait_for_job_result_async_returns_fetched_value():
17791857
async def run() -> None:
17801858
status_values = iter(["running", "completed"])
@@ -1850,6 +1928,34 @@ async def fetch_result() -> dict:
18501928
asyncio.run(run())
18511929

18521930

1931+
def test_wait_for_job_result_async_retries_request_timeout_fetch_errors():
1932+
async def run() -> None:
1933+
fetch_attempts = {"count": 0}
1934+
1935+
async def fetch_result() -> dict:
1936+
fetch_attempts["count"] += 1
1937+
if fetch_attempts["count"] < 3:
1938+
raise HyperbrowserError("request timeout", status_code=408)
1939+
return {"ok": True}
1940+
1941+
result = await wait_for_job_result_async(
1942+
operation_name="async wait helper request-timeout retries",
1943+
get_status=lambda: asyncio.sleep(0, result="completed"),
1944+
is_terminal_status=lambda value: value == "completed",
1945+
fetch_result=fetch_result,
1946+
poll_interval_seconds=0.0001,
1947+
max_wait_seconds=1.0,
1948+
max_status_failures=2,
1949+
fetch_max_attempts=5,
1950+
fetch_retry_delay_seconds=0.0001,
1951+
)
1952+
1953+
assert result == {"ok": True}
1954+
assert fetch_attempts["count"] == 3
1955+
1956+
asyncio.run(run())
1957+
1958+
18531959
def test_wait_for_job_result_validates_configuration():
18541960
with pytest.raises(HyperbrowserError, match="max_attempts must be at least 1"):
18551961
wait_for_job_result(

0 commit comments

Comments
 (0)