Skip to content

Commit 2ef6eb7

Browse files
Add process readiness documentation
Documents the new process readiness feature from PR #273 including: - serve() method for starting servers with automatic readiness and exposure - waitFor() method for waiting on process conditions - ready and readyTimeout options for startProcess() - Support for string, RegExp, and port-based readiness conditions - ProcessReadyTimeoutError and ProcessExitedBeforeReadyError handling Updates: - API reference (commands.mdx): Full documentation for serve(), waitFor(), and updated startProcess() - Background processes guide: Comprehensive examples of readiness patterns - Expose services guide: Simplified workflow using serve() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 1f2b21b commit 2ef6eb7

File tree

3 files changed

+335
-49
lines changed

3 files changed

+335
-49
lines changed

src/content/docs/sandbox/api/commands.mdx

Lines changed: 142 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,42 @@ for await (const event of parseSSEStream<ExecEvent>(stream)) {
8787
Start a long-running background process.
8888

8989
```ts
90-
const process = await sandbox.startProcess(command: string, options?: ProcessOptions): Promise<ProcessInfo>
90+
const process = await sandbox.startProcess(command: string, options?: ProcessOptions): Promise<Process>
9191
```
9292

9393
**Parameters**:
9494
- `command` - The command to start as a background process
9595
- `options` (optional):
9696
- `cwd` - Working directory
9797
- `env` - Environment variables
98+
- `ready` - Condition to wait for before returning (string, RegExp, or port number)
99+
- `readyTimeout` - Maximum time to wait for ready condition in milliseconds (default: `30000`)
98100

99-
**Returns**: `Promise<ProcessInfo>` with `id`, `pid`, `command`, `status`
101+
**Returns**: `Promise<Process>` with `id`, `pid`, `command`, `status`, and methods:
102+
- `waitFor(condition, timeout?)` - Wait for additional conditions
100103

101104
<TypeScriptExample>
102105
```
106+
// Basic usage
103107
const server = await sandbox.startProcess('python -m http.server 8000');
104108
console.log('Started with PID:', server.pid);
105109
106-
// With custom environment
107-
const app = await sandbox.startProcess('node app.js', {
110+
// Wait for log pattern before proceeding
111+
const app = await sandbox.startProcess('npm start', {
112+
ready: 'Server listening on port 3000',
113+
readyTimeout: 30000
114+
});
115+
116+
// Wait for port to be available
117+
const api = await sandbox.startProcess('node app.js', {
118+
ready: 8080,
108119
cwd: '/workspace/my-app',
109-
env: { NODE_ENV: 'production', PORT: '3000' }
120+
env: { NODE_ENV: 'production' }
121+
});
122+
123+
// Wait for regex pattern
124+
const db = await sandbox.startProcess('postgres', {
125+
ready: /database system is ready/i
110126
});
111127
```
112128
</TypeScriptExample>
@@ -195,21 +211,139 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
195211
Get accumulated logs from a process.
196212

197213
```ts
198-
const logs = await sandbox.getProcessLogs(processId: string): Promise<string>
214+
const logs = await sandbox.getProcessLogs(processId: string): Promise<{ stdout: string, stderr: string }>
199215
```
200216

201217
**Parameters**:
202218
- `processId` - The process ID
203219

204-
**Returns**: `Promise<string>` with all accumulated output
220+
**Returns**: `Promise<{ stdout: string, stderr: string }>` with all accumulated output
205221

206222
<TypeScriptExample>
207223
```
208224
const server = await sandbox.startProcess('node server.js');
209225
await new Promise(resolve => setTimeout(resolve, 5000));
210226
211227
const logs = await sandbox.getProcessLogs(server.id);
212-
console.log('Server logs:', logs);
228+
console.log('Server logs:', logs.stdout);
229+
console.log('Server errors:', logs.stderr);
230+
```
231+
</TypeScriptExample>
232+
233+
### `serve()`
234+
235+
Start a server process, wait for it to be ready, and optionally expose it with a preview URL.
236+
237+
```ts
238+
const result = await sandbox.serve(
239+
command: string,
240+
portOrOptions: number | ServeOptions
241+
): Promise<string | { url: string, process: Process }>
242+
```
243+
244+
**Parameters**:
245+
- `command` - The command to start the server
246+
- `portOrOptions` - Port number or options object:
247+
- `port` - Port number to expose
248+
- `hostname` - Hostname for preview URL (required for URL exposure)
249+
- `ready` - Custom readiness condition (defaults to port check)
250+
- `timeout` - Readiness timeout in milliseconds (default: `60000`)
251+
- `env` - Environment variables
252+
- `cwd` - Working directory
253+
254+
**Returns**:
255+
- If `hostname` provided: `Promise<{ url: string, process: Process }>` with preview URL
256+
- If no `hostname`: `Promise<string>` with local URL indication
257+
258+
<TypeScriptExample>
259+
```
260+
// Simple port exposure with preview URL
261+
const { url, process } = await sandbox.serve('npm start', {
262+
port: 3000,
263+
hostname: request.url.hostname
264+
});
265+
266+
console.log('Server accessible at:', url);
267+
268+
// With custom readiness pattern
269+
const { url, process } = await sandbox.serve('python -m http.server 8080', {
270+
port: 8080,
271+
hostname: request.url.hostname,
272+
ready: 'Serving HTTP',
273+
timeout: 60000
274+
});
275+
276+
// Without hostname (for internal use)
277+
const localUrl = await sandbox.serve('node api.js', 3000);
278+
// Returns: "http://localhost:3000"
279+
```
280+
</TypeScriptExample>
281+
282+
### `process.waitFor()`
283+
284+
Wait for a condition to be met for a running process. Available on the `Process` object returned by `startProcess()`.
285+
286+
```ts
287+
const result = await process.waitFor(
288+
condition: ReadyCondition,
289+
timeout?: number
290+
): Promise<WaitForResult>
291+
```
292+
293+
**Parameters**:
294+
- `condition` - String pattern, RegExp, or port number to wait for
295+
- `timeout` - Maximum wait time in milliseconds (default: `30000`)
296+
297+
**Returns**: `Promise<WaitForResult>` with:
298+
- `line` - The matching log line (for string/regex conditions)
299+
- `match` - RegExp capture groups (for regex conditions)
300+
301+
<TypeScriptExample>
302+
```
303+
const app = await sandbox.startProcess('npm run dev');
304+
305+
// Wait for database connection
306+
await app.waitFor('Database connected');
307+
308+
// Wait for port availability
309+
await app.waitFor(3000);
310+
311+
// Wait for regex with capture groups
312+
const result = await app.waitFor(/Server started on port (\d+)/);
313+
console.log('Port:', result.match?.[1]); // "3000"
314+
315+
// With custom timeout
316+
await app.waitFor('Ready', 60000);
317+
```
318+
</TypeScriptExample>
319+
320+
## Error handling
321+
322+
Process readiness operations may throw specific errors:
323+
324+
<TypeScriptExample>
325+
```
326+
import {
327+
ProcessReadyTimeoutError,
328+
ProcessExitedBeforeReadyError
329+
} from '@cloudflare/sandbox';
330+
331+
try {
332+
const server = await sandbox.startProcess('npm start', {
333+
ready: 'Server listening',
334+
readyTimeout: 10000
335+
});
336+
} catch (error) {
337+
if (error instanceof ProcessReadyTimeoutError) {
338+
// Process did not become ready in time
339+
console.error('Timeout waiting for:', error.condition);
340+
console.error('Last output:', error.stdout, error.stderr);
341+
} else if (error instanceof ProcessExitedBeforeReadyError) {
342+
// Process crashed before becoming ready
343+
console.error('Process exited with code:', error.exitCode);
344+
console.error('Output:', error.stdout, error.stderr);
345+
}
346+
}
213347
```
214348
</TypeScriptExample>
215349

0 commit comments

Comments
 (0)