|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -from typing import Dict, Optional |
| 5 | +from typing import Any, Dict, Optional |
6 | 6 |
|
7 | 7 | import httpx |
8 | 8 |
|
|
21 | 21 | from ...types.devboxes import disk_snapshot_list_params, disk_snapshot_update_params |
22 | 22 | from ...types.devbox_snapshot_view import DevboxSnapshotView |
23 | 23 | from ...types.devboxes.devbox_snapshot_async_status_view import DevboxSnapshotAsyncStatusView |
| 24 | +from ..._exceptions import RunloopError |
| 25 | +from ...lib.polling import PollingConfig, poll_until |
| 26 | +from ...lib.polling_async import async_poll_until |
24 | 27 |
|
25 | 28 | __all__ = ["DiskSnapshotsResource", "AsyncDiskSnapshotsResource"] |
26 | 29 |
|
@@ -239,6 +242,29 @@ def query_status( |
239 | 242 | cast_to=DevboxSnapshotAsyncStatusView, |
240 | 243 | ) |
241 | 244 |
|
| 245 | + def await_completed( |
| 246 | + self, |
| 247 | + id: str, |
| 248 | + *, |
| 249 | + polling_config: PollingConfig | None = None, |
| 250 | + **request_options: Any, |
| 251 | + ) -> DevboxSnapshotAsyncStatusView: |
| 252 | + """Wait for a disk snapshot operation to complete.""" |
| 253 | + |
| 254 | + if not id: |
| 255 | + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") |
| 256 | + |
| 257 | + def is_terminal(result: DevboxSnapshotAsyncStatusView) -> bool: |
| 258 | + return result.status in {"complete", "error"} |
| 259 | + |
| 260 | + status = poll_until(lambda: self.query_status(id, **request_options), is_terminal, polling_config) |
| 261 | + |
| 262 | + if status.status == "error": |
| 263 | + message = status.error_message or "Unknown error" |
| 264 | + raise RunloopError(f"Snapshot {id} failed: {message}") |
| 265 | + |
| 266 | + return status |
| 267 | + |
242 | 268 |
|
243 | 269 | class AsyncDiskSnapshotsResource(AsyncAPIResource): |
244 | 270 | @cached_property |
@@ -454,6 +480,33 @@ async def query_status( |
454 | 480 | cast_to=DevboxSnapshotAsyncStatusView, |
455 | 481 | ) |
456 | 482 |
|
| 483 | + async def await_completed( |
| 484 | + self, |
| 485 | + id: str, |
| 486 | + *, |
| 487 | + polling_config: PollingConfig | None = None, |
| 488 | + **request_options: Any, |
| 489 | + ) -> DevboxSnapshotAsyncStatusView: |
| 490 | + """Wait asynchronously for a disk snapshot operation to complete.""" |
| 491 | + |
| 492 | + if not id: |
| 493 | + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") |
| 494 | + |
| 495 | + def is_terminal(result: DevboxSnapshotAsyncStatusView) -> bool: |
| 496 | + return result.status in {"complete", "error"} |
| 497 | + |
| 498 | + status = await async_poll_until( |
| 499 | + lambda: self.query_status(id, **request_options), |
| 500 | + is_terminal, |
| 501 | + polling_config, |
| 502 | + ) |
| 503 | + |
| 504 | + if status.status == "error": |
| 505 | + message = status.error_message or "Unknown error" |
| 506 | + raise RunloopError(f"Snapshot {id} failed: {message}") |
| 507 | + |
| 508 | + return status |
| 509 | + |
457 | 510 |
|
458 | 511 | class DiskSnapshotsResourceWithRawResponse: |
459 | 512 | def __init__(self, disk_snapshots: DiskSnapshotsResource) -> None: |
|
0 commit comments