Skip to content

Commit c06794d

Browse files
feat(mux): wait_for_eviction endpoint for flex eviction notifications (#10325)
1 parent cfc97ef commit c06794d

6 files changed

Lines changed: 137 additions & 4 deletions

File tree

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 119
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-d0efdaa19d8a5685def3947450df7f9bdaf9bad3243317d514add5d22129fc5f.yml
3-
openapi_spec_hash: 7e484ea9f60294503bf4691fe3efef3a
4-
config_hash: 218b8d25038e627faab98532392ee9a0
1+
configured_endpoints: 120
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai/runloop-f18b1bba718700c841b3904207cd8ba2c066421a691845d6283bbbb361cf161d.yml
3+
openapi_spec_hash: 6044f4a4da13881c5f82fcc394c1f43b
4+
config_hash: d9a5b7a4227236a55c89de56b56f4aec

api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ from runloop_api_client.types import (
214214
TunnelView,
215215
DevboxCreateSSHKeyResponse,
216216
DevboxReadFileContentsResponse,
217+
DevboxWatchEvictionsResponse,
217218
)
218219
```
219220

@@ -244,6 +245,7 @@ Methods:
244245
- <code title="post /v1/devboxes/{id}/suspend">client.devboxes.<a href="./src/runloop_api_client/resources/devboxes/devboxes.py">suspend</a>(id) -> <a href="./src/runloop_api_client/types/devbox_view.py">DevboxView</a></code>
245246
- <code title="post /v1/devboxes/{id}/upload_file">client.devboxes.<a href="./src/runloop_api_client/resources/devboxes/devboxes.py">upload_file</a>(id, \*\*<a href="src/runloop_api_client/types/devbox_upload_file_params.py">params</a>) -> object</code>
246247
- <code title="post /v1/devboxes/{devbox_id}/executions/{execution_id}/wait_for_status">client.devboxes.<a href="./src/runloop_api_client/resources/devboxes/devboxes.py">wait_for_command</a>(execution_id, \*, devbox_id, \*\*<a href="src/runloop_api_client/types/devbox_wait_for_command_params.py">params</a>) -> <a href="./src/runloop_api_client/types/devbox_async_execution_detail_view.py">DevboxAsyncExecutionDetailView</a></code>
248+
- <code title="get /v1/devboxes/watch_evictions">client.devboxes.<a href="./src/runloop_api_client/resources/devboxes/devboxes.py">watch_evictions</a>() -> <a href="./src/runloop_api_client/types/devbox_watch_evictions_response.py">DevboxWatchEvictionsResponse</a></code>
247249
- <code title="post /v1/devboxes/{id}/write_file_contents">client.devboxes.<a href="./src/runloop_api_client/resources/devboxes/devboxes.py">write_file_contents</a>(id, \*\*<a href="src/runloop_api_client/types/devbox_write_file_contents_params.py">params</a>) -> <a href="./src/runloop_api_client/types/devbox_execution_detail_view.py">DevboxExecutionDetailView</a></code>
248250

249251

src/runloop_api_client/resources/devboxes/devboxes.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
from ...types.devbox_resource_usage_view import DevboxResourceUsageView
9898
from ...types.devbox_execution_detail_view import DevboxExecutionDetailView
9999
from ...types.devbox_create_ssh_key_response import DevboxCreateSSHKeyResponse
100+
from ...types.devbox_watch_evictions_response import DevboxWatchEvictionsResponse
100101
from ...types.shared_params.launch_parameters import LaunchParameters
101102
from ...types.devbox_async_execution_detail_view import DevboxAsyncExecutionDetailView
102103
from ...types.shared_params.code_mount_parameters import CodeMountParameters
@@ -1742,6 +1743,31 @@ def wait_for_command(
17421743
cast_to=DevboxAsyncExecutionDetailView,
17431744
)
17441745

1746+
def watch_evictions(
1747+
self,
1748+
*,
1749+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1750+
# The extra values given here take precedence over values defined on the client or passed to this method.
1751+
extra_headers: Headers | None = None,
1752+
extra_query: Query | None = None,
1753+
extra_body: Body | None = None,
1754+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
1755+
) -> DevboxWatchEvictionsResponse:
1756+
"""
1757+
Subscribe, via server-sent events, to pending infrastructure evictions for every
1758+
Devbox in the account. On connect the stream emits one event per Devbox that
1759+
currently has a pending eviction, then one event as each further eviction is
1760+
scheduled. Best-effort and advisory: a Devbox stays running until its deadline,
1761+
and delivery is not guaranteed.
1762+
"""
1763+
return self._get(
1764+
"/v1/devboxes/watch_evictions",
1765+
options=make_request_options(
1766+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
1767+
),
1768+
cast_to=DevboxWatchEvictionsResponse,
1769+
)
1770+
17451771
def write_file_contents(
17461772
self,
17471773
id: str,
@@ -3417,6 +3443,31 @@ async def wait_for_command(
34173443
cast_to=DevboxAsyncExecutionDetailView,
34183444
)
34193445

3446+
async def watch_evictions(
3447+
self,
3448+
*,
3449+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
3450+
# The extra values given here take precedence over values defined on the client or passed to this method.
3451+
extra_headers: Headers | None = None,
3452+
extra_query: Query | None = None,
3453+
extra_body: Body | None = None,
3454+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
3455+
) -> DevboxWatchEvictionsResponse:
3456+
"""
3457+
Subscribe, via server-sent events, to pending infrastructure evictions for every
3458+
Devbox in the account. On connect the stream emits one event per Devbox that
3459+
currently has a pending eviction, then one event as each further eviction is
3460+
scheduled. Best-effort and advisory: a Devbox stays running until its deadline,
3461+
and delivery is not guaranteed.
3462+
"""
3463+
return await self._get(
3464+
"/v1/devboxes/watch_evictions",
3465+
options=make_request_options(
3466+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
3467+
),
3468+
cast_to=DevboxWatchEvictionsResponse,
3469+
)
3470+
34203471
async def write_file_contents(
34213472
self,
34223473
id: str,
@@ -3555,6 +3606,9 @@ def __init__(self, devboxes: DevboxesResource) -> None:
35553606
self.wait_for_command = to_raw_response_wrapper(
35563607
devboxes.wait_for_command,
35573608
)
3609+
self.watch_evictions = to_raw_response_wrapper(
3610+
devboxes.watch_evictions,
3611+
)
35583612
self.write_file_contents = to_raw_response_wrapper(
35593613
devboxes.write_file_contents,
35603614
)
@@ -3651,6 +3705,9 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
36513705
self.wait_for_command = async_to_raw_response_wrapper(
36523706
devboxes.wait_for_command,
36533707
)
3708+
self.watch_evictions = async_to_raw_response_wrapper(
3709+
devboxes.watch_evictions,
3710+
)
36543711
self.write_file_contents = async_to_raw_response_wrapper(
36553712
devboxes.write_file_contents,
36563713
)
@@ -3747,6 +3804,9 @@ def __init__(self, devboxes: DevboxesResource) -> None:
37473804
self.wait_for_command = to_streamed_response_wrapper(
37483805
devboxes.wait_for_command,
37493806
)
3807+
self.watch_evictions = to_streamed_response_wrapper(
3808+
devboxes.watch_evictions,
3809+
)
37503810
self.write_file_contents = to_streamed_response_wrapper(
37513811
devboxes.write_file_contents,
37523812
)
@@ -3843,6 +3903,9 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
38433903
self.wait_for_command = async_to_streamed_response_wrapper(
38443904
devboxes.wait_for_command,
38453905
)
3906+
self.watch_evictions = async_to_streamed_response_wrapper(
3907+
devboxes.watch_evictions,
3908+
)
38463909
self.write_file_contents = async_to_streamed_response_wrapper(
38473910
devboxes.write_file_contents,
38483911
)

src/runloop_api_client/types/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
from .blueprint_build_logs_list_view import BlueprintBuildLogsListView as BlueprintBuildLogsListView
140140
from .devbox_create_ssh_key_response import DevboxCreateSSHKeyResponse as DevboxCreateSSHKeyResponse
141141
from .devbox_wait_for_command_params import DevboxWaitForCommandParams as DevboxWaitForCommandParams
142+
from .devbox_watch_evictions_response import DevboxWatchEvictionsResponse as DevboxWatchEvictionsResponse
142143
from .devbox_read_file_contents_params import DevboxReadFileContentsParams as DevboxReadFileContentsParams
143144
from .benchmark_update_scenarios_params import BenchmarkUpdateScenariosParams as BenchmarkUpdateScenariosParams
144145
from .devbox_list_disk_snapshots_params import DevboxListDiskSnapshotsParams as DevboxListDiskSnapshotsParams
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from .._models import BaseModel
4+
5+
__all__ = ["DevboxWatchEvictionsResponse"]
6+
7+
8+
class DevboxWatchEvictionsResponse(BaseModel):
9+
devbox_id: str
10+
"""The ID of the Devbox with a pending eviction."""
11+
12+
eviction_deadline_ms: int
13+
"""Unix timestamp (milliseconds) after which the Devbox will be suspended.
14+
15+
Advisory and best-effort.
16+
"""

tests/api_resources/test_devboxes.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
DevboxResourceUsageView,
2121
DevboxExecutionDetailView,
2222
DevboxCreateSSHKeyResponse,
23+
DevboxWatchEvictionsResponse,
2324
DevboxAsyncExecutionDetailView,
2425
)
2526
from runloop_api_client._response import (
@@ -1190,6 +1191,31 @@ def test_path_params_wait_for_command(self, client: Runloop) -> None:
11901191
statuses=["queued"],
11911192
)
11921193

1194+
@parametrize
1195+
def test_method_watch_evictions(self, client: Runloop) -> None:
1196+
devbox = client.devboxes.watch_evictions()
1197+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
1198+
1199+
@parametrize
1200+
def test_raw_response_watch_evictions(self, client: Runloop) -> None:
1201+
response = client.devboxes.with_raw_response.watch_evictions()
1202+
1203+
assert response.is_closed is True
1204+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
1205+
devbox = response.parse()
1206+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
1207+
1208+
@parametrize
1209+
def test_streaming_response_watch_evictions(self, client: Runloop) -> None:
1210+
with client.devboxes.with_streaming_response.watch_evictions() as response:
1211+
assert not response.is_closed
1212+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
1213+
1214+
devbox = response.parse()
1215+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
1216+
1217+
assert cast(Any, response.is_closed) is True
1218+
11931219
@parametrize
11941220
def test_method_write_file_contents(self, client: Runloop) -> None:
11951221
devbox = client.devboxes.write_file_contents(
@@ -2859,6 +2885,31 @@ async def test_path_params_wait_for_command(self, async_client: AsyncRunloop) ->
28592885
statuses=["queued"],
28602886
)
28612887

2888+
@parametrize
2889+
async def test_method_watch_evictions(self, async_client: AsyncRunloop) -> None:
2890+
devbox = await async_client.devboxes.watch_evictions()
2891+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
2892+
2893+
@parametrize
2894+
async def test_raw_response_watch_evictions(self, async_client: AsyncRunloop) -> None:
2895+
response = await async_client.devboxes.with_raw_response.watch_evictions()
2896+
2897+
assert response.is_closed is True
2898+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
2899+
devbox = await response.parse()
2900+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
2901+
2902+
@parametrize
2903+
async def test_streaming_response_watch_evictions(self, async_client: AsyncRunloop) -> None:
2904+
async with async_client.devboxes.with_streaming_response.watch_evictions() as response:
2905+
assert not response.is_closed
2906+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
2907+
2908+
devbox = await response.parse()
2909+
assert_matches_type(DevboxWatchEvictionsResponse, devbox, path=["response"])
2910+
2911+
assert cast(Any, response.is_closed) is True
2912+
28622913
@parametrize
28632914
async def test_method_write_file_contents(self, async_client: AsyncRunloop) -> None:
28642915
devbox = await async_client.devboxes.write_file_contents(

0 commit comments

Comments
 (0)