Skip to content

Commit 2a4f021

Browse files
committed
added await_suspended methods to base api
1 parent b7cc6e2 commit 2a4f021

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

‎src/runloop_api_client/resources/devboxes/devboxes.py‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,50 @@ def is_done_booting(devbox: DevboxView) -> bool:
426426

427427
return devbox
428428

429+
def await_suspended(
430+
self,
431+
id: str,
432+
*,
433+
polling_config: PollingConfig | None = None,
434+
) -> DevboxView:
435+
"""Wait for a devbox to reach the suspended state.
436+
437+
Args:
438+
id: The ID of the devbox to wait for.
439+
polling_config: Optional polling configuration.
440+
441+
Returns:
442+
The devbox in the suspended state.
443+
444+
Raises:
445+
PollingTimeout: If polling times out before the devbox is suspended.
446+
RunloopError: If the devbox enters a non-suspended terminal state.
447+
"""
448+
449+
def wait_for_devbox_status() -> DevboxView:
450+
return self._post(
451+
f"/v1/devboxes/{id}/wait_for_status",
452+
body={"statuses": ["suspended", "failure", "shutdown"]},
453+
cast_to=DevboxView,
454+
)
455+
456+
def handle_timeout_error(error: Exception) -> DevboxView:
457+
if isinstance(error, APITimeoutError) or (
458+
isinstance(error, APIStatusError) and error.response.status_code == 408
459+
):
460+
return placeholder_devbox_view(id)
461+
raise error
462+
463+
def is_terminal_state(devbox: DevboxView) -> bool:
464+
return devbox.status in {"suspended", "failure", "shutdown"}
465+
466+
devbox = poll_until(wait_for_devbox_status, is_terminal_state, polling_config, handle_timeout_error)
467+
468+
if devbox.status != "suspended":
469+
raise RunloopError(f"Devbox entered non-suspended terminal state: {devbox.status}")
470+
471+
return devbox
472+
429473
def create_and_await_running(
430474
self,
431475
*,
@@ -1921,6 +1965,48 @@ def is_done_booting(devbox: DevboxView) -> bool:
19211965

19221966
return devbox
19231967

1968+
async def await_suspended(
1969+
self,
1970+
id: str,
1971+
*,
1972+
polling_config: PollingConfig | None = None,
1973+
) -> DevboxView:
1974+
"""Wait for a devbox to reach the suspended state.
1975+
1976+
Args:
1977+
id: The ID of the devbox to wait for.
1978+
polling_config: Optional polling configuration.
1979+
1980+
Returns:
1981+
The devbox in the suspended state.
1982+
1983+
Raises:
1984+
PollingTimeout: If polling times out before the devbox is suspended.
1985+
RunloopError: If the devbox enters a non-suspended terminal state.
1986+
"""
1987+
1988+
async def wait_for_devbox_status() -> DevboxView:
1989+
try:
1990+
return await self._post(
1991+
f"/v1/devboxes/{id}/wait_for_status",
1992+
body={"statuses": ["suspended", "failure", "shutdown"]},
1993+
cast_to=DevboxView,
1994+
)
1995+
except (APITimeoutError, APIStatusError) as error:
1996+
if isinstance(error, APITimeoutError) or error.response.status_code == 408:
1997+
return placeholder_devbox_view(id)
1998+
raise
1999+
2000+
def is_terminal_state(devbox: DevboxView) -> bool:
2001+
return devbox.status in {"suspended", "failure", "shutdown"}
2002+
2003+
devbox = await async_poll_until(wait_for_devbox_status, is_terminal_state, polling_config)
2004+
2005+
if devbox.status != "suspended":
2006+
raise RunloopError(f"Devbox entered non-suspended terminal state: {devbox.status}")
2007+
2008+
return devbox
2009+
19242010
async def update(
19252011
self,
19262012
id: str,

0 commit comments

Comments
 (0)