@@ -2455,6 +2455,64 @@ def test_wait_for_job_result_returns_fetched_value():
24552455 assert result == {"ok" : True }
24562456
24572457
2458+ def test_wait_for_job_result_status_polling_failures_short_circuit_fetch ():
2459+ status_attempts = {"count" : 0 }
2460+ fetch_attempts = {"count" : 0 }
2461+
2462+ def get_status () -> str :
2463+ status_attempts ["count" ] += 1
2464+ raise ValueError ("temporary failure" )
2465+
2466+ def fetch_result () -> dict :
2467+ fetch_attempts ["count" ] += 1
2468+ return {"ok" : True }
2469+
2470+ with pytest .raises (HyperbrowserPollingError , match = "Failed to poll" ):
2471+ wait_for_job_result (
2472+ operation_name = "sync wait helper polling failures" ,
2473+ get_status = get_status ,
2474+ is_terminal_status = lambda value : value == "completed" ,
2475+ fetch_result = fetch_result ,
2476+ poll_interval_seconds = 0.0001 ,
2477+ max_wait_seconds = 1.0 ,
2478+ max_status_failures = 2 ,
2479+ fetch_max_attempts = 5 ,
2480+ fetch_retry_delay_seconds = 0.0001 ,
2481+ )
2482+
2483+ assert status_attempts ["count" ] == 2
2484+ assert fetch_attempts ["count" ] == 0
2485+
2486+
2487+ def test_wait_for_job_result_status_timeout_short_circuits_fetch ():
2488+ status_attempts = {"count" : 0 }
2489+ fetch_attempts = {"count" : 0 }
2490+
2491+ def get_status () -> str :
2492+ status_attempts ["count" ] += 1
2493+ return "running"
2494+
2495+ def fetch_result () -> dict :
2496+ fetch_attempts ["count" ] += 1
2497+ return {"ok" : True }
2498+
2499+ with pytest .raises (HyperbrowserTimeoutError , match = "Timed out waiting for" ):
2500+ wait_for_job_result (
2501+ operation_name = "sync wait helper status timeout" ,
2502+ get_status = get_status ,
2503+ is_terminal_status = lambda value : value == "completed" ,
2504+ fetch_result = fetch_result ,
2505+ poll_interval_seconds = 0.0001 ,
2506+ max_wait_seconds = 0 ,
2507+ max_status_failures = 5 ,
2508+ fetch_max_attempts = 5 ,
2509+ fetch_retry_delay_seconds = 0.0001 ,
2510+ )
2511+
2512+ assert status_attempts ["count" ] == 1
2513+ assert fetch_attempts ["count" ] == 0
2514+
2515+
24582516def test_wait_for_job_result_does_not_retry_non_retryable_status_errors ():
24592517 status_attempts = {"count" : 0 }
24602518 fetch_attempts = {"count" : 0 }
@@ -2887,6 +2945,70 @@ async def run() -> None:
28872945 asyncio .run (run ())
28882946
28892947
2948+ def test_wait_for_job_result_async_status_polling_failures_short_circuit_fetch ():
2949+ async def run () -> None :
2950+ status_attempts = {"count" : 0 }
2951+ fetch_attempts = {"count" : 0 }
2952+
2953+ async def get_status () -> str :
2954+ status_attempts ["count" ] += 1
2955+ raise ValueError ("temporary failure" )
2956+
2957+ async def fetch_result () -> dict :
2958+ fetch_attempts ["count" ] += 1
2959+ return {"ok" : True }
2960+
2961+ with pytest .raises (HyperbrowserPollingError , match = "Failed to poll" ):
2962+ await wait_for_job_result_async (
2963+ operation_name = "async wait helper polling failures" ,
2964+ get_status = get_status ,
2965+ is_terminal_status = lambda value : value == "completed" ,
2966+ fetch_result = fetch_result ,
2967+ poll_interval_seconds = 0.0001 ,
2968+ max_wait_seconds = 1.0 ,
2969+ max_status_failures = 2 ,
2970+ fetch_max_attempts = 5 ,
2971+ fetch_retry_delay_seconds = 0.0001 ,
2972+ )
2973+
2974+ assert status_attempts ["count" ] == 2
2975+ assert fetch_attempts ["count" ] == 0
2976+
2977+ asyncio .run (run ())
2978+
2979+
2980+ def test_wait_for_job_result_async_status_timeout_short_circuits_fetch ():
2981+ async def run () -> None :
2982+ status_attempts = {"count" : 0 }
2983+ fetch_attempts = {"count" : 0 }
2984+
2985+ async def get_status () -> str :
2986+ status_attempts ["count" ] += 1
2987+ return "running"
2988+
2989+ async def fetch_result () -> dict :
2990+ fetch_attempts ["count" ] += 1
2991+ return {"ok" : True }
2992+
2993+ with pytest .raises (HyperbrowserTimeoutError , match = "Timed out waiting for" ):
2994+ await wait_for_job_result_async (
2995+ operation_name = "async wait helper status timeout" ,
2996+ get_status = get_status ,
2997+ is_terminal_status = lambda value : value == "completed" ,
2998+ fetch_result = fetch_result ,
2999+ poll_interval_seconds = 0.0001 ,
3000+ max_wait_seconds = 0 ,
3001+ max_status_failures = 5 ,
3002+ fetch_max_attempts = 5 ,
3003+ fetch_retry_delay_seconds = 0.0001 ,
3004+ )
3005+
3006+ assert status_attempts ["count" ] == 1
3007+ assert fetch_attempts ["count" ] == 0
3008+
3009+ asyncio .run (run ())
3010+
3011+
28903012def test_wait_for_job_result_async_does_not_retry_non_retryable_status_errors ():
28913013 async def run () -> None :
28923014 status_attempts = {"count" : 0 }
0 commit comments