Skip to content

Commit 090942f

Browse files
committed
Add long poll endpoint for querying async exec status
1 parent 68ae32c commit 090942f

1 file changed

Lines changed: 52 additions & 20 deletions

File tree

src/runloop_api_client/resources/devboxes/executions.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from ...lib.polling_async import async_poll_until
2424
from ...types.devbox_execution_detail_view import DevboxExecutionDetailView
2525
from ...types.devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView
26+
from ..._exceptions import APIStatusError
2627

2728
__all__ = ["ExecutionsResource", "AsyncExecutionsResource"]
2829

@@ -121,20 +122,37 @@ def await_completed(
121122
Raises:
122123
PollingTimeout: If polling times out before execution completes
123124
"""
124-
def retrieve_execution() -> DevboxAsyncExecutionDetailView:
125-
return self.retrieve(
126-
execution_id,
127-
devbox_id=devbox_id,
128-
extra_headers=extra_headers,
129-
extra_query=extra_query,
130-
extra_body=extra_body,
131-
timeout=timeout
125+
126+
def wait_for_execution_status() -> DevboxAsyncExecutionDetailView:
127+
# This wait_for_status endpoint polls the execution status for 60 seconds until it reaches either completed.
128+
return self._post(
129+
f"/v1/devboxes/{devbox_id}/executions/{execution_id}/wait_for_status",
130+
body={"statuses": ["completed"]},
131+
options=make_request_options(
132+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
133+
),
134+
cast_to=DevboxAsyncExecutionDetailView,
132135
)
136+
137+
def handle_timeout_error(error: Exception) -> DevboxAsyncExecutionDetailView:
138+
# Handle 408 timeout errors by returning current execution state to continue polling
139+
if isinstance(error, APIStatusError) and error.response.status_code == 408:
140+
# Return a placeholder result to continue polling
141+
return DevboxAsyncExecutionDetailView(
142+
devbox_id=devbox_id,
143+
execution_id=execution_id,
144+
status="queued",
145+
stdout="",
146+
stderr="",
147+
)
148+
else:
149+
# Re-raise other errors to stop polling
150+
raise error
133151

134152
def is_done(execution: DevboxAsyncExecutionDetailView) -> bool:
135153
return execution.status == 'completed'
136154

137-
return poll_until(retrieve_execution, is_done, config)
155+
return poll_until(wait_for_execution_status, is_done, config, handle_timeout_error)
138156

139157
def execute_async(
140158
self,
@@ -397,20 +415,34 @@ async def await_completed(
397415
Raises:
398416
PollingTimeout: If polling times out before execution completes
399417
"""
400-
async def retrieve_execution() -> DevboxAsyncExecutionDetailView:
401-
return await self.retrieve(
402-
execution_id,
403-
devbox_id=devbox_id,
404-
extra_headers=extra_headers,
405-
extra_query=extra_query,
406-
extra_body=extra_body,
407-
timeout=timeout,
408-
)
418+
async def wait_for_execution_status() -> DevboxAsyncExecutionDetailView:
419+
try:
420+
return await self._post(
421+
f"/v1/devboxes/{devbox_id}/executions/{execution_id}/wait_for_status",
422+
body={"statuses": ["completed"]},
423+
options=make_request_options(
424+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
425+
),
426+
cast_to=DevboxAsyncExecutionDetailView,
427+
)
428+
except APIStatusError as error:
429+
if error.response.status_code == 408:
430+
# Handle 408 timeout errors by returning current execution state to continue polling
431+
return DevboxAsyncExecutionDetailView(
432+
devbox_id=devbox_id,
433+
execution_id=execution_id,
434+
status="queued",
435+
stdout="",
436+
stderr="",
437+
)
438+
else:
439+
# Re-raise other errors to stop polling
440+
raise
409441

410442
def is_done(execution: DevboxAsyncExecutionDetailView) -> bool:
411443
return execution.status == 'completed'
412-
413-
return await async_poll_until(retrieve_execution, is_done, polling_config)
444+
445+
return await async_poll_until(wait_for_execution_status, is_done, polling_config)
414446

415447
async def execute_async(
416448
self,

0 commit comments

Comments
 (0)