Skip to content

Commit 27380f9

Browse files
Cover wait-helper terminal callback fail-fast behavior
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 28412e3 commit 27380f9

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

‎tests/test_polling.py‎

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,74 @@ def fetch_result() -> dict:
25712571
assert fetch_attempts["count"] == 0
25722572

25732573

2574+
def test_wait_for_job_result_does_not_retry_terminal_callback_errors():
2575+
status_attempts = {"count": 0}
2576+
fetch_attempts = {"count": 0}
2577+
2578+
def get_status() -> str:
2579+
status_attempts["count"] += 1
2580+
return "completed"
2581+
2582+
def fetch_result() -> dict:
2583+
fetch_attempts["count"] += 1
2584+
return {"ok": True}
2585+
2586+
with pytest.raises(HyperbrowserError, match="is_terminal_status failed"):
2587+
wait_for_job_result(
2588+
operation_name="sync wait helper terminal callback exception",
2589+
get_status=get_status,
2590+
is_terminal_status=lambda value: (_ for _ in ()).throw(ValueError("boom")),
2591+
fetch_result=fetch_result,
2592+
poll_interval_seconds=0.0001,
2593+
max_wait_seconds=1.0,
2594+
max_status_failures=5,
2595+
fetch_max_attempts=5,
2596+
fetch_retry_delay_seconds=0.0001,
2597+
)
2598+
2599+
assert status_attempts["count"] == 1
2600+
assert fetch_attempts["count"] == 0
2601+
2602+
2603+
def test_wait_for_job_result_cancels_awaitable_terminal_callback_results():
2604+
status_attempts = {"count": 0}
2605+
fetch_attempts = {"count": 0}
2606+
loop = asyncio.new_event_loop()
2607+
try:
2608+
callback_future = loop.create_future()
2609+
2610+
def get_status() -> str:
2611+
status_attempts["count"] += 1
2612+
return "completed"
2613+
2614+
def fetch_result() -> dict:
2615+
fetch_attempts["count"] += 1
2616+
return {"ok": True}
2617+
2618+
with pytest.raises(
2619+
HyperbrowserError,
2620+
match="is_terminal_status must return a non-awaitable result",
2621+
):
2622+
wait_for_job_result(
2623+
operation_name="sync wait helper terminal callback future",
2624+
get_status=get_status,
2625+
is_terminal_status=lambda value: callback_future, # type: ignore[return-value]
2626+
fetch_result=fetch_result,
2627+
poll_interval_seconds=0.0001,
2628+
max_wait_seconds=1.0,
2629+
max_status_failures=5,
2630+
fetch_max_attempts=5,
2631+
fetch_retry_delay_seconds=0.0001,
2632+
)
2633+
2634+
assert callback_future.cancelled()
2635+
finally:
2636+
loop.close()
2637+
2638+
assert status_attempts["count"] == 1
2639+
assert fetch_attempts["count"] == 0
2640+
2641+
25742642
def test_wait_for_job_result_retries_rate_limit_status_errors():
25752643
status_attempts = {"count": 0}
25762644
fetch_attempts = {"count": 0}
@@ -2916,6 +2984,77 @@ async def fetch_result() -> dict:
29162984
asyncio.run(run())
29172985

29182986

2987+
def test_wait_for_job_result_async_does_not_retry_terminal_callback_errors():
2988+
async def run() -> None:
2989+
status_attempts = {"count": 0}
2990+
fetch_attempts = {"count": 0}
2991+
2992+
async def get_status() -> str:
2993+
status_attempts["count"] += 1
2994+
return "completed"
2995+
2996+
async def fetch_result() -> dict:
2997+
fetch_attempts["count"] += 1
2998+
return {"ok": True}
2999+
3000+
with pytest.raises(HyperbrowserError, match="is_terminal_status failed"):
3001+
await wait_for_job_result_async(
3002+
operation_name="async wait helper terminal callback exception",
3003+
get_status=get_status,
3004+
is_terminal_status=lambda value: (_ for _ in ()).throw(
3005+
ValueError("boom")
3006+
),
3007+
fetch_result=fetch_result,
3008+
poll_interval_seconds=0.0001,
3009+
max_wait_seconds=1.0,
3010+
max_status_failures=5,
3011+
fetch_max_attempts=5,
3012+
fetch_retry_delay_seconds=0.0001,
3013+
)
3014+
3015+
assert status_attempts["count"] == 1
3016+
assert fetch_attempts["count"] == 0
3017+
3018+
asyncio.run(run())
3019+
3020+
3021+
def test_wait_for_job_result_async_cancels_awaitable_terminal_callback_results():
3022+
async def run() -> None:
3023+
status_attempts = {"count": 0}
3024+
fetch_attempts = {"count": 0}
3025+
callback_future = asyncio.get_running_loop().create_future()
3026+
3027+
async def get_status() -> str:
3028+
status_attempts["count"] += 1
3029+
return "completed"
3030+
3031+
async def fetch_result() -> dict:
3032+
fetch_attempts["count"] += 1
3033+
return {"ok": True}
3034+
3035+
with pytest.raises(
3036+
HyperbrowserError,
3037+
match="is_terminal_status must return a non-awaitable result",
3038+
):
3039+
await wait_for_job_result_async(
3040+
operation_name="async wait helper terminal callback future",
3041+
get_status=get_status,
3042+
is_terminal_status=lambda value: callback_future, # type: ignore[return-value]
3043+
fetch_result=fetch_result,
3044+
poll_interval_seconds=0.0001,
3045+
max_wait_seconds=1.0,
3046+
max_status_failures=5,
3047+
fetch_max_attempts=5,
3048+
fetch_retry_delay_seconds=0.0001,
3049+
)
3050+
3051+
assert callback_future.cancelled()
3052+
assert status_attempts["count"] == 1
3053+
assert fetch_attempts["count"] == 0
3054+
3055+
asyncio.run(run())
3056+
3057+
29193058
def test_wait_for_job_result_async_retries_rate_limit_status_errors():
29203059
async def run() -> None:
29213060
status_attempts = {"count": 0}

0 commit comments

Comments
 (0)