Skip to content

Commit 028127c

Browse files
committed
Strengthen timeout handling in api call
1 parent 234104d commit 028127c

File tree

1 file changed

+84
-63
lines changed

1 file changed

+84
-63
lines changed

chipflow_lib/steps/silicon.py

Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
logger = logging.getLogger(__name__)
2323

24-
2524
class SiliconTop(StepBase, Elaboratable):
2625
def __init__(self, config={}):
2726
self._config = config
@@ -191,68 +190,7 @@ def submit(self, rtlil_path, *, dry_run=False, wait=False):
191190
resp_data = resp.text
192191

193192
# Handle response based on status code
194-
if resp.status_code == 200:
195-
logger.info(f"Submitted design: {resp_data}")
196-
build_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}"
197-
build_status_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}/status"
198-
log_stream_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}/logs?follow=true"
199-
200-
print(f"Design submitted successfully! Build URL: {build_url}")
201-
202-
# Poll the status API until the build is completed or failed
203-
stream_event_counter = 0
204-
fail_counter = 0
205-
if wait:
206-
while True:
207-
logger.info("Polling build status...")
208-
status_resp = requests.get(
209-
build_status_url,
210-
auth=(None, chipflow_api_key)
211-
)
212-
if status_resp.status_code != 200:
213-
fail_counter += 1
214-
logger.error(f"Failed to fetch build status {fail_counter} times: {status_resp.text}")
215-
if fail_counter > 5:
216-
logger.error(f"Failed to fetch build status {fail_counter} times. Exiting.")
217-
raise ChipFlowError("Error while checking build status.")
218-
219-
status_data = status_resp.json()
220-
build_status = status_data.get("status")
221-
logger.info(f"Build status: {build_status}")
222-
223-
if build_status == "completed":
224-
print("Build completed successfully!")
225-
exit(0)
226-
elif build_status == "failed":
227-
print("Build failed.")
228-
exit(1)
229-
elif build_status == "running":
230-
print("Build running.")
231-
# Wait before polling again
232-
# time.sleep(10)
233-
# Attempt to stream logs rather than time.sleep
234-
try:
235-
if stream_event_counter > 1:
236-
logger.warning("Log streaming may have been interrupted. Some logs may be missing.")
237-
logger.warning(f"Check {build_url}")
238-
stream_event_counter += 1
239-
with requests.get(
240-
log_stream_url,
241-
auth=(None, chipflow_api_key),
242-
stream=True
243-
) as log_resp:
244-
if log_resp.status_code == 200:
245-
for line in log_resp.iter_lines():
246-
if line:
247-
print(line.decode("utf-8")) # Print logs in real-time
248-
sys.stdout.flush()
249-
else:
250-
logger.warning(f"Failed to stream logs: {log_resp.text}")
251-
except requests.RequestException as e:
252-
logger.error(f"Error while streaming logs: {e}")
253-
pass
254-
time.sleep(10) # Wait before polling again
255-
else:
193+
if resp.status_code != 200:
256194
# Log detailed information about the failed request
257195
logger.error(f"Request failed with status code {resp.status_code}")
258196
logger.error(f"Request URL: {resp.request.url}")
@@ -268,3 +206,86 @@ def submit(self, rtlil_path, *, dry_run=False, wait=False):
268206
logger.error(f"Response body: {resp_data}")
269207

270208
raise ChipFlowError(f"Failed to submit design: {resp_data}")
209+
210+
logger.info(f"Submitted design: {resp_data}")
211+
build_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}"
212+
build_status_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}/status"
213+
log_stream_url = f"{chipflow_api_origin}/build/{resp_data['build_id']}/logs?follow=true"
214+
215+
print(f"Design submitted successfully! Build URL: {build_url}")
216+
217+
# Poll the status API until the build is completed or failed
218+
timeout = 10.0
219+
220+
def stream_until_fail_or_done():
221+
nonlocal timeout
222+
fail_count = 0
223+
print_log_warning = False
224+
while fail_count < (2*60//timeout):
225+
try:
226+
if fail_count > 1:
227+
print_log_warning = True
228+
with requests.get(
229+
log_stream_url,
230+
auth=(None, chipflow_api_key),
231+
stream=True, timeout=timeout
232+
) as log_resp:
233+
if log_resp.status_code == 200:
234+
for line in log_resp.iter_lines():
235+
if line:
236+
print(line.decode("utf-8")) # Print logs in real-time
237+
sys.stdout.flush()
238+
else:
239+
logger.warning(f"Failed to stream logs: {log_resp.text}")
240+
fail_count += 1
241+
except requests.Timeout:
242+
fail_count +=1
243+
continue #go round again
244+
except requests.RequestException as e:
245+
if type(e) is requests.exceptions.ConnectionError and e.response is None:
246+
fail_count +=1
247+
continue #try again
248+
logger.error(f"Error while streaming logs: {type(e)}:{e} response={e.response}")
249+
return "failed"
250+
status_data = status_resp.json()
251+
build_status = status_data.get("status")
252+
if print_log_warning:
253+
logger.warning("Log streaming may have been interrupted. Some logs may be missing.")
254+
logger.warning(f"Check {build_url}")
255+
256+
return build_status
257+
258+
259+
if not wait:
260+
exit(0)
261+
262+
fail_count = 0
263+
while True:
264+
logger.info("Polling build status...")
265+
try:
266+
status_resp = requests.get(
267+
build_status_url,
268+
auth=(None, chipflow_api_key),
269+
timeout=timeout
270+
)
271+
if status_resp.status_code != 200:
272+
fail_count += 1
273+
logger.error(f"Failed to fetch build status {fail_count} times: {status_resp.text}")
274+
if fail_count > 5:
275+
logger.error(f"Failed to fetch build status {fail_count} times. Exiting.")
276+
raise ChipFlowError("Error while checking build status.")
277+
except requests.Timeout:
278+
continue #go round again
279+
280+
build_status = stream_until_fail_or_done()
281+
if build_status == "completed":
282+
print("Build completed successfully!")
283+
exit(0)
284+
elif build_status == "failed":
285+
print("Build failed.")
286+
exit(1)
287+
elif build_status == "running":
288+
print("Build running.")
289+
# Wait before polling again
290+
time.sleep(0.5) # Wait before polling again
291+

0 commit comments

Comments
 (0)