@@ -182,6 +182,28 @@ def get_status() -> str:
182182 assert attempts ["count" ] == 3
183183
184184
185+ def test_poll_until_terminal_status_retries_request_timeout_errors ():
186+ attempts = {"count" : 0 }
187+
188+ def get_status () -> str :
189+ attempts ["count" ] += 1
190+ if attempts ["count" ] < 3 :
191+ raise HyperbrowserError ("request timeout" , status_code = 408 )
192+ return "completed"
193+
194+ status = poll_until_terminal_status (
195+ operation_name = "sync poll request-timeout retries" ,
196+ get_status = get_status ,
197+ is_terminal_status = lambda value : value == "completed" ,
198+ poll_interval_seconds = 0.0001 ,
199+ max_wait_seconds = 1.0 ,
200+ max_status_failures = 5 ,
201+ )
202+
203+ assert status == "completed"
204+ assert attempts ["count" ] == 3
205+
206+
185207def test_poll_until_terminal_status_async_retries_rate_limit_errors ():
186208 async def run () -> None :
187209 attempts = {"count" : 0 }
@@ -207,6 +229,31 @@ async def get_status() -> str:
207229 asyncio .run (run ())
208230
209231
232+ def test_poll_until_terminal_status_async_retries_request_timeout_errors ():
233+ async def run () -> None :
234+ attempts = {"count" : 0 }
235+
236+ async def get_status () -> str :
237+ attempts ["count" ] += 1
238+ if attempts ["count" ] < 3 :
239+ raise HyperbrowserError ("request timeout" , status_code = 408 )
240+ return "completed"
241+
242+ status = await poll_until_terminal_status_async (
243+ operation_name = "async poll request-timeout retries" ,
244+ get_status = get_status ,
245+ is_terminal_status = lambda value : value == "completed" ,
246+ poll_interval_seconds = 0.0001 ,
247+ max_wait_seconds = 1.0 ,
248+ max_status_failures = 5 ,
249+ )
250+
251+ assert status == "completed"
252+ assert attempts ["count" ] == 3
253+
254+ asyncio .run (run ())
255+
256+
210257def test_poll_until_terminal_status_async_handles_non_integer_status_codes_as_retryable ():
211258 async def run () -> None :
212259 attempts = {"count" : 0 }
@@ -437,6 +484,26 @@ def operation() -> str:
437484 assert attempts ["count" ] == 3
438485
439486
487+ def test_retry_operation_retries_request_timeout_errors ():
488+ attempts = {"count" : 0 }
489+
490+ def operation () -> str :
491+ attempts ["count" ] += 1
492+ if attempts ["count" ] < 3 :
493+ raise HyperbrowserError ("request timeout" , status_code = 408 )
494+ return "ok"
495+
496+ result = retry_operation (
497+ operation_name = "sync retry request-timeout error" ,
498+ operation = operation ,
499+ max_attempts = 5 ,
500+ retry_delay_seconds = 0.0001 ,
501+ )
502+
503+ assert result == "ok"
504+ assert attempts ["count" ] == 3
505+
506+
440507def test_retry_operation_handles_non_integer_status_codes_as_retryable ():
441508 attempts = {"count" : 0 }
442509
@@ -748,6 +815,29 @@ async def operation() -> str:
748815 asyncio .run (run ())
749816
750817
818+ def test_retry_operation_async_retries_request_timeout_errors ():
819+ async def run () -> None :
820+ attempts = {"count" : 0 }
821+
822+ async def operation () -> str :
823+ attempts ["count" ] += 1
824+ if attempts ["count" ] < 3 :
825+ raise HyperbrowserError ("request timeout" , status_code = 408 )
826+ return "ok"
827+
828+ result = await retry_operation_async (
829+ operation_name = "async retry request-timeout error" ,
830+ operation = operation ,
831+ max_attempts = 5 ,
832+ retry_delay_seconds = 0.0001 ,
833+ )
834+
835+ assert result == "ok"
836+ assert attempts ["count" ] == 3
837+
838+ asyncio .run (run ())
839+
840+
751841def test_async_poll_until_terminal_status_allows_immediate_terminal_on_zero_max_wait ():
752842 async def run () -> None :
753843 status = await poll_until_terminal_status_async (
0 commit comments