55
66import anyio
77import httpx
8+ from tenacity import (
9+ retry ,
10+ retry_if_exception ,
11+ stop_after_attempt ,
12+ wait_exponential ,
13+ )
814
915from .codebox import CodeBox
1016from .types import ExecChunk , RemoteFile
@@ -46,6 +52,14 @@ def __init__(
4652 self .client = httpx .Client (base_url = self .url , headers = self .headers )
4753 self .aclient = httpx .AsyncClient (base_url = self .url , headers = self .headers )
4854
55+ @retry (
56+ retry = retry_if_exception (
57+ lambda e : isinstance (e , httpx .HTTPStatusError )
58+ and e .response .status_code == 502
59+ ),
60+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
61+ stop = stop_after_attempt (3 ),
62+ )
4963 def stream_exec (
5064 self ,
5165 code : t .Union [str , PathLike ],
@@ -72,6 +86,14 @@ def stream_exec(
7286 yield ExecChunk (type = t , content = c ) # type: ignore[arg-type]
7387 buffer = buffer [end :]
7488
89+ @retry (
90+ retry = retry_if_exception (
91+ lambda e : isinstance (e , httpx .HTTPStatusError )
92+ and e .response .status_code == 502
93+ ),
94+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
95+ stop = stop_after_attempt (3 ),
96+ )
7597 async def astream_exec (
7698 self ,
7799 code : t .Union [str , PathLike ],
@@ -105,6 +127,14 @@ async def astream_exec(
105127 async for c in self .astream_exec (code , kernel , timeout , cwd ):
106128 yield c
107129
130+ @retry (
131+ retry = retry_if_exception (
132+ lambda e : isinstance (e , httpx .HTTPStatusError )
133+ and e .response .status_code == 502
134+ ),
135+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
136+ stop = stop_after_attempt (3 ),
137+ )
108138 def upload (
109139 self ,
110140 file_name : str ,
@@ -122,6 +152,14 @@ def upload(
122152 ).raise_for_status ()
123153 return RemoteFile (path = file_name , remote = self )
124154
155+ @retry (
156+ retry = retry_if_exception (
157+ lambda e : isinstance (e , httpx .HTTPStatusError )
158+ and e .response .status_code == 502
159+ ),
160+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
161+ stop = stop_after_attempt (3 ),
162+ )
125163 async def aupload (
126164 self ,
127165 remote_file_path : str ,
@@ -140,6 +178,14 @@ async def aupload(
140178 response .raise_for_status ()
141179 return RemoteFile (path = remote_file_path , remote = self )
142180
181+ @retry (
182+ retry = retry_if_exception (
183+ lambda e : isinstance (e , httpx .HTTPStatusError )
184+ and e .response .status_code == 502
185+ ),
186+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
187+ stop = stop_after_attempt (3 ),
188+ )
143189 def stream_download (
144190 self ,
145191 remote_file_path : str ,
@@ -150,9 +196,18 @@ def stream_download(
150196 url = f"/files/download/{ remote_file_path } " ,
151197 timeout = timeout ,
152198 ) as response :
199+ response .raise_for_status ()
153200 for chunk in response .iter_bytes ():
154201 yield chunk
155202
203+ @retry (
204+ retry = retry_if_exception (
205+ lambda e : isinstance (e , httpx .HTTPStatusError )
206+ and e .response .status_code == 502
207+ ),
208+ wait = wait_exponential (multiplier = 1 , min = 5 , max = 150 ),
209+ stop = stop_after_attempt (3 ),
210+ )
156211 async def astream_download (
157212 self ,
158213 remote_file_path : str ,
@@ -163,5 +218,6 @@ async def astream_download(
163218 url = f"/files/download/{ remote_file_path } " ,
164219 timeout = timeout ,
165220 ) as response :
221+ response .raise_for_status ()
166222 async for chunk in response .aiter_bytes ():
167223 yield chunk
0 commit comments