@@ -146,6 +146,29 @@ def get_status() -> str:
146146 assert attempts ["count" ] == 1
147147
148148
149+ def test_poll_until_terminal_status_does_not_retry_bytearray_client_errors ():
150+ attempts = {"count" : 0 }
151+
152+ def get_status () -> str :
153+ attempts ["count" ] += 1
154+ raise HyperbrowserError (
155+ "client failure" ,
156+ status_code = bytearray (b"400" ), # type: ignore[arg-type]
157+ )
158+
159+ with pytest .raises (HyperbrowserError , match = "client failure" ):
160+ poll_until_terminal_status (
161+ operation_name = "sync poll bytearray client error" ,
162+ get_status = get_status ,
163+ is_terminal_status = lambda value : value == "completed" ,
164+ poll_interval_seconds = 0.0001 ,
165+ max_wait_seconds = 1.0 ,
166+ max_status_failures = 5 ,
167+ )
168+
169+ assert attempts ["count" ] == 1
170+
171+
149172def test_poll_until_terminal_status_does_not_retry_memoryview_client_errors ():
150173 attempts = {"count" : 0 }
151174
@@ -832,6 +855,29 @@ def operation() -> str:
832855 assert attempts ["count" ] == 3
833856
834857
858+ def test_retry_operation_retries_bytearray_rate_limit_errors ():
859+ attempts = {"count" : 0 }
860+
861+ def operation () -> str :
862+ attempts ["count" ] += 1
863+ if attempts ["count" ] < 3 :
864+ raise HyperbrowserError (
865+ "rate limited" ,
866+ status_code = bytearray (b"429" ), # type: ignore[arg-type]
867+ )
868+ return "ok"
869+
870+ result = retry_operation (
871+ operation_name = "sync retry bytearray rate limit" ,
872+ operation = operation ,
873+ max_attempts = 5 ,
874+ retry_delay_seconds = 0.0001 ,
875+ )
876+
877+ assert result == "ok"
878+ assert attempts ["count" ] == 3
879+
880+
835881def test_retry_operation_retries_memoryview_rate_limit_errors ():
836882 attempts = {"count" : 0 }
837883
@@ -1381,6 +1427,32 @@ async def get_status() -> str:
13811427 asyncio .run (run ())
13821428
13831429
1430+ def test_poll_until_terminal_status_async_does_not_retry_bytearray_client_errors ():
1431+ async def run () -> None :
1432+ attempts = {"count" : 0 }
1433+
1434+ async def get_status () -> str :
1435+ attempts ["count" ] += 1
1436+ raise HyperbrowserError (
1437+ "client failure" ,
1438+ status_code = bytearray (b"404" ), # type: ignore[arg-type]
1439+ )
1440+
1441+ with pytest .raises (HyperbrowserError , match = "client failure" ):
1442+ await poll_until_terminal_status_async (
1443+ operation_name = "async poll bytearray client error" ,
1444+ get_status = get_status ,
1445+ is_terminal_status = lambda value : value == "completed" ,
1446+ poll_interval_seconds = 0.0001 ,
1447+ max_wait_seconds = 1.0 ,
1448+ max_status_failures = 5 ,
1449+ )
1450+
1451+ assert attempts ["count" ] == 1
1452+
1453+ asyncio .run (run ())
1454+
1455+
13841456def test_poll_until_terminal_status_async_does_not_retry_memoryview_client_errors ():
13851457 async def run () -> None :
13861458 attempts = {"count" : 0 }
@@ -1742,6 +1814,32 @@ async def operation() -> str:
17421814 asyncio .run (run ())
17431815
17441816
1817+ def test_retry_operation_async_retries_bytearray_rate_limit_errors ():
1818+ async def run () -> None :
1819+ attempts = {"count" : 0 }
1820+
1821+ async def operation () -> str :
1822+ attempts ["count" ] += 1
1823+ if attempts ["count" ] < 3 :
1824+ raise HyperbrowserError (
1825+ "rate limited" ,
1826+ status_code = bytearray (b"429" ), # type: ignore[arg-type]
1827+ )
1828+ return "ok"
1829+
1830+ result = await retry_operation_async (
1831+ operation_name = "async retry bytearray rate limit" ,
1832+ operation = operation ,
1833+ max_attempts = 5 ,
1834+ retry_delay_seconds = 0.0001 ,
1835+ )
1836+
1837+ assert result == "ok"
1838+ assert attempts ["count" ] == 3
1839+
1840+ asyncio .run (run ())
1841+
1842+
17451843def test_retry_operation_async_retries_memoryview_rate_limit_errors ():
17461844 async def run () -> None :
17471845 attempts = {"count" : 0 }
@@ -3845,6 +3943,38 @@ def fetch_result() -> dict:
38453943 assert fetch_attempts ["count" ] == 0
38463944
38473945
3946+ def test_wait_for_job_result_does_not_retry_bytearray_status_errors ():
3947+ status_attempts = {"count" : 0 }
3948+ fetch_attempts = {"count" : 0 }
3949+
3950+ def get_status () -> str :
3951+ status_attempts ["count" ] += 1
3952+ raise HyperbrowserError (
3953+ "client failure" ,
3954+ status_code = bytearray (b"400" ), # type: ignore[arg-type]
3955+ )
3956+
3957+ def fetch_result () -> dict :
3958+ fetch_attempts ["count" ] += 1
3959+ return {"ok" : True }
3960+
3961+ with pytest .raises (HyperbrowserError , match = "client failure" ):
3962+ wait_for_job_result (
3963+ operation_name = "sync wait helper status bytearray client error" ,
3964+ get_status = get_status ,
3965+ is_terminal_status = lambda value : value == "completed" ,
3966+ fetch_result = fetch_result ,
3967+ poll_interval_seconds = 0.0001 ,
3968+ max_wait_seconds = 1.0 ,
3969+ max_status_failures = 5 ,
3970+ fetch_max_attempts = 5 ,
3971+ fetch_retry_delay_seconds = 0.0001 ,
3972+ )
3973+
3974+ assert status_attempts ["count" ] == 1
3975+ assert fetch_attempts ["count" ] == 0
3976+
3977+
38483978def test_wait_for_job_result_does_not_retry_numeric_bytes_status_errors ():
38493979 status_attempts = {"count" : 0 }
38503980 fetch_attempts = {"count" : 0 }
@@ -4522,6 +4652,34 @@ def fetch_result() -> dict:
45224652 assert fetch_attempts ["count" ] == 3
45234653
45244654
4655+ def test_wait_for_job_result_retries_bytearray_rate_limit_fetch_errors ():
4656+ fetch_attempts = {"count" : 0 }
4657+
4658+ def fetch_result () -> dict :
4659+ fetch_attempts ["count" ] += 1
4660+ if fetch_attempts ["count" ] < 3 :
4661+ raise HyperbrowserError (
4662+ "rate limited" ,
4663+ status_code = bytearray (b"429" ), # type: ignore[arg-type]
4664+ )
4665+ return {"ok" : True }
4666+
4667+ result = wait_for_job_result (
4668+ operation_name = "sync wait helper fetch bytearray rate limit" ,
4669+ get_status = lambda : "completed" ,
4670+ is_terminal_status = lambda value : value == "completed" ,
4671+ fetch_result = fetch_result ,
4672+ poll_interval_seconds = 0.0001 ,
4673+ max_wait_seconds = 1.0 ,
4674+ max_status_failures = 5 ,
4675+ fetch_max_attempts = 5 ,
4676+ fetch_retry_delay_seconds = 0.0001 ,
4677+ )
4678+
4679+ assert result == {"ok" : True }
4680+ assert fetch_attempts ["count" ] == 3
4681+
4682+
45254683def test_wait_for_job_result_retries_numeric_bytes_rate_limit_fetch_errors ():
45264684 fetch_attempts = {"count" : 0 }
45274685
@@ -4783,6 +4941,41 @@ async def fetch_result() -> dict:
47834941 asyncio .run (run ())
47844942
47854943
4944+ def test_wait_for_job_result_async_does_not_retry_bytearray_status_errors ():
4945+ async def run () -> None :
4946+ status_attempts = {"count" : 0 }
4947+ fetch_attempts = {"count" : 0 }
4948+
4949+ async def get_status () -> str :
4950+ status_attempts ["count" ] += 1
4951+ raise HyperbrowserError (
4952+ "client failure" ,
4953+ status_code = bytearray (b"404" ), # type: ignore[arg-type]
4954+ )
4955+
4956+ async def fetch_result () -> dict :
4957+ fetch_attempts ["count" ] += 1
4958+ return {"ok" : True }
4959+
4960+ with pytest .raises (HyperbrowserError , match = "client failure" ):
4961+ await wait_for_job_result_async (
4962+ operation_name = "async wait helper status bytearray client error" ,
4963+ get_status = get_status ,
4964+ is_terminal_status = lambda value : value == "completed" ,
4965+ fetch_result = fetch_result ,
4966+ poll_interval_seconds = 0.0001 ,
4967+ max_wait_seconds = 1.0 ,
4968+ max_status_failures = 5 ,
4969+ fetch_max_attempts = 5 ,
4970+ fetch_retry_delay_seconds = 0.0001 ,
4971+ )
4972+
4973+ assert status_attempts ["count" ] == 1
4974+ assert fetch_attempts ["count" ] == 0
4975+
4976+ asyncio .run (run ())
4977+
4978+
47864979def test_wait_for_job_result_async_does_not_retry_numeric_bytes_status_errors ():
47874980 async def run () -> None :
47884981 status_attempts = {"count" : 0 }
@@ -5523,6 +5716,37 @@ async def fetch_result() -> dict:
55235716 asyncio .run (run ())
55245717
55255718
5719+ def test_wait_for_job_result_async_retries_bytearray_rate_limit_fetch_errors ():
5720+ async def run () -> None :
5721+ fetch_attempts = {"count" : 0 }
5722+
5723+ async def fetch_result () -> dict :
5724+ fetch_attempts ["count" ] += 1
5725+ if fetch_attempts ["count" ] < 3 :
5726+ raise HyperbrowserError (
5727+ "rate limited" ,
5728+ status_code = bytearray (b"429" ), # type: ignore[arg-type]
5729+ )
5730+ return {"ok" : True }
5731+
5732+ result = await wait_for_job_result_async (
5733+ operation_name = "async wait helper fetch bytearray rate limit" ,
5734+ get_status = lambda : asyncio .sleep (0 , result = "completed" ),
5735+ is_terminal_status = lambda value : value == "completed" ,
5736+ fetch_result = fetch_result ,
5737+ poll_interval_seconds = 0.0001 ,
5738+ max_wait_seconds = 1.0 ,
5739+ max_status_failures = 5 ,
5740+ fetch_max_attempts = 5 ,
5741+ fetch_retry_delay_seconds = 0.0001 ,
5742+ )
5743+
5744+ assert result == {"ok" : True }
5745+ assert fetch_attempts ["count" ] == 3
5746+
5747+ asyncio .run (run ())
5748+
5749+
55265750def test_wait_for_job_result_async_retries_numeric_bytes_rate_limit_fetch_errors ():
55275751 async def run () -> None :
55285752 fetch_attempts = {"count" : 0 }
0 commit comments