Skip to content

Commit e814e00

Browse files
authored
feat(devbox): added suspend async and promoted suspend to automatically await the devbox running (#670)
1 parent 042865b commit e814e00

4 files changed

Lines changed: 55 additions & 7 deletions

File tree

src/sdk/devbox.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -885,18 +885,38 @@ export class Devbox {
885885
}
886886

887887
/**
888-
* Resume a suspended devbox.
888+
* Resume a suspended devbox and wait for it to reach the running state.
889889
*
890890
* @example
891891
* ```typescript
892892
* await devbox.resume();
893+
* // Devbox is now running
894+
* ```
895+
*
896+
* @param {Core.RequestOptions & { polling?: Partial<PollingOptions<DevboxView>> }} [options] - Request options with optional polling configuration
897+
* @returns {Promise<DevboxView>} The devbox data when running state is reached
898+
*/
899+
async resume(
900+
options?: Core.RequestOptions & { polling?: Partial<PollingOptions<DevboxView>> },
901+
): Promise<DevboxView> {
902+
await this.resumeAsync(options);
903+
return this.awaitRunning(options);
904+
}
905+
906+
/**
907+
* Resume a suspended devbox without waiting for it to reach the running state.
908+
*
909+
* @example
910+
* ```typescript
911+
* await devbox.resumeAsync();
912+
* // Optionally wait for running state
893913
* await devbox.awaitRunning();
894914
* ```
895915
*
896916
* @param {Core.RequestOptions} [options] - Request options
897917
* @returns {Promise<DevboxResumeResponse>} Resume result
898918
*/
899-
async resume(options?: Core.RequestOptions) {
919+
async resumeAsync(options?: Core.RequestOptions) {
900920
return this.client.devboxes.resume(this._id, options);
901921
}
902922

tests/objects/devbox.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ describe('Devbox (New API)', () => {
2323
shutdown: jest.fn(),
2424
suspend: jest.fn(),
2525
resume: jest.fn(),
26+
awaitRunning: jest.fn(),
27+
awaitSuspended: jest.fn(),
2628
keepAlive: jest.fn(),
2729
snapshotDisk: jest.fn(),
2830
snapshotDiskAsync: jest.fn(),
@@ -208,12 +210,15 @@ describe('Devbox (New API)', () => {
208210
});
209211

210212
it('should resume the devbox', async () => {
213+
const mockRunningData = { ...mockDevboxData, status: 'running' as const };
211214
mockClient.devboxes.resume.mockResolvedValue(undefined);
215+
mockClient.devboxes.awaitRunning.mockResolvedValue(mockRunningData);
212216

213217
const result = await devbox.resume();
214218

215219
expect(mockClient.devboxes.resume).toHaveBeenCalledWith('devbox-123', undefined);
216-
expect(result).toBeUndefined(); // Should return API response
220+
expect(mockClient.devboxes.awaitRunning).toHaveBeenCalledWith('devbox-123', undefined);
221+
expect(result).toEqual(mockRunningData); // Should return devbox data when running
217222
});
218223
});
219224

tests/smoketests/object-oriented/devbox.test.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,38 @@ describe('smoketest: object-oriented devbox', () => {
137137
const suspendedInfo = await devbox.getInfo();
138138
expect(suspendedInfo.status).toBe('suspended');
139139

140-
// Resume the devbox
141-
await devbox.resume();
142-
await devbox.awaitRunning();
143-
const resumedInfo = await devbox.getInfo();
140+
// Resume the devbox - resume() automatically waits for running state
141+
const resumedInfo = await devbox.resume();
144142
expect(resumedInfo.status).toBe('running');
145143

146144
// Clean up
147145
await devbox.shutdown();
148146
});
149147

148+
test('resumeAsync - resume without waiting', async () => {
149+
const devbox = await sdk.devbox.create({
150+
name: uniqueName('sdk-devbox-resume-async'),
151+
launch_parameters: { resource_size_request: 'X_SMALL', keep_alive_time_seconds: 60 * 5 }, // 5 minutes
152+
});
153+
154+
// Suspend the devbox
155+
await devbox.suspend();
156+
await devbox.awaitSuspended();
157+
const suspendedInfo = await devbox.getInfo();
158+
expect(suspendedInfo.status).toBe('suspended');
159+
160+
// Resume the devbox asynchronously - doesn't wait automatically
161+
const resumeResponse = await devbox.resumeAsync();
162+
expect(resumeResponse).toBeDefined();
163+
164+
// Now wait for running state explicitly
165+
const runningInfo = await devbox.awaitRunning();
166+
expect(runningInfo.status).toBe('running');
167+
168+
// Clean up
169+
await devbox.shutdown();
170+
});
171+
150172
test('keep alive', async () => {
151173
const devbox = await sdk.devbox.create({
152174
name: uniqueName('sdk-devbox-keepalive'),

tests/smoketests/object-oriented/execution.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe('smoketest: object-oriented execution', () => {
4949
expect(result.exitCode).toBe(0);
5050
expect(result.success).toBe(true);
5151
expect(result.failed).toBe(false);
52+
expect(result.executionId).toBeTruthy();
5253
expect(result.result).toBeDefined();
5354

5455
const output = await result.stdout();

0 commit comments

Comments
 (0)