Skip to content

Commit 62af520

Browse files
committed
Strengthen timeout handling in api call
1 parent 234104d commit 62af520

File tree

1 file changed

+83
-63
lines changed

1 file changed

+83
-63
lines changed

chipflow_lib/steps/silicon.py

Lines changed: 83 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,85 @@ 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+
stream_event_counter = 0
219+
warned_last = False
220+
timeout = 10.0
221+
222+
def stream_until_fail_or_done():
223+
nonlocal warned_last
224+
nonlocal timeout
225+
nonlocal stream_event_counter
226+
fail_count = 0
227+
while fail_count < (2*60//timeout):
228+
try:
229+
if stream_event_counter > 1 and not warned_last:
230+
logger.warning("Log streaming may have been interrupted. Some logs may be missing.")
231+
logger.warning(f"Check {build_url}")
232+
warned_last = True
233+
with requests.get(
234+
log_stream_url,
235+
auth=(None, chipflow_api_key),
236+
stream=True, timeout=timeout
237+
) as log_resp:
238+
if log_resp.status_code == 200:
239+
warned_last = False
240+
for line in log_resp.iter_lines():
241+
if line:
242+
print(line.decode("utf-8")) # Print logs in real-time
243+
sys.stdout.flush()
244+
else:
245+
logger.warning(f"Failed to stream logs: {log_resp.text}")
246+
stream_event_counter += 1
247+
except requests.Timeout:
248+
continue #go round again
249+
except requests.RequestException as e:
250+
logger.error(f"Error while streaming logs: {e}")
251+
stream_event_counter += 1
252+
return "failed"
253+
status_data = status_resp.json()
254+
build_status = status_data.get("status")
255+
return build_status
256+
257+
258+
if not wait:
259+
exit(0)
260+
261+
fail_counter = 0
262+
while True:
263+
logger.info("Polling build status...")
264+
try:
265+
status_resp = requests.get(
266+
build_status_url,
267+
auth=(None, chipflow_api_key),
268+
timeout=timeout
269+
)
270+
if status_resp.status_code != 200:
271+
fail_counter += 1
272+
logger.error(f"Failed to fetch build status {fail_counter} times: {status_resp.text}")
273+
if fail_counter > 5:
274+
logger.error(f"Failed to fetch build status {fail_counter} times. Exiting.")
275+
raise ChipFlowError("Error while checking build status.")
276+
except requests.Timeout:
277+
continue #go round again
278+
279+
build_status = stream_until_fail_or_done()
280+
if build_status == "completed":
281+
print("Build completed successfully!")
282+
exit(0)
283+
elif build_status == "failed":
284+
print("Build failed.")
285+
exit(1)
286+
elif build_status == "running":
287+
print("Build running.")
288+
# Wait before polling again
289+
time.sleep(0.5) # Wait before polling again
290+

0 commit comments

Comments
 (0)