Skip to content

Commit 650095e

Browse files
Add process readiness documentation
Documents the new process readiness feature added in PR #273, including: - waitFor() method for waiting on log patterns, regex, or ports - serve() method for starting servers with automatic readiness checks - ready and readyTimeout options for startProcess() - ProcessReadyTimeoutError and ProcessExitedBeforeReadyError handling Updates: - Background processes guide with comprehensive readiness examples - Commands API reference with new methods and options 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 32081ec commit 650095e

File tree

2 files changed

+224
-21
lines changed

2 files changed

+224
-21
lines changed

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

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,106 @@ 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 pattern, regex, or port number)
99+
- `readyTimeout` - Timeout in milliseconds for readiness check (default: 30000)
98100

99-
**Returns**: `Promise<ProcessInfo>` with `id`, `pid`, `command`, `status`
101+
**Returns**: `Promise<Process>` with `id`, `pid`, `command`, `status`, and methods
100102

101103
<TypeScriptExample>
102104
```
103105
const server = await sandbox.startProcess('python -m http.server 8000');
104106
console.log('Started with PID:', server.pid);
105107
106-
// With custom environment
107-
const app = await sandbox.startProcess('node app.js', {
108+
// Wait for process to be ready before continuing
109+
const app = await sandbox.startProcess('npm start', {
108110
cwd: '/workspace/my-app',
109-
env: { NODE_ENV: 'production', PORT: '3000' }
111+
env: { NODE_ENV: 'production', PORT: '3000' },
112+
ready: 'Server listening on port 3000',
113+
readyTimeout: 30000
110114
});
115+
116+
// App is now ready to accept connections
117+
```
118+
</TypeScriptExample>
119+
120+
### `serve()`
121+
122+
Start a server process, wait for it to be ready, and optionally expose it with a preview URL.
123+
124+
```ts
125+
const result = await sandbox.serve(command: string, portOrOptions: number | ServeOptions): Promise<string | { url: string; process: Process }>
126+
```
127+
128+
**Parameters**:
129+
- `command` - The command to start
130+
- `portOrOptions` - Port number or options object:
131+
- `port` - Port number to wait for
132+
- `hostname` - Hostname for preview URL (optional)
133+
- `ready` - Log pattern to wait for before checking port (optional)
134+
- `timeout` - Timeout in milliseconds (default: 60000)
135+
- `env` - Environment variables (optional)
136+
- `cwd` - Working directory (optional)
137+
138+
**Returns**:
139+
- If `hostname` is provided: `Promise<{ url: string; process: Process }>`
140+
- If no `hostname`: `Promise<string>` with local URL
141+
142+
<TypeScriptExample>
143+
```
144+
// Simple usage - wait for port only
145+
const url = await sandbox.serve('npm start', 3000);
146+
147+
// With hostname to get preview URL
148+
const { url, process } = await sandbox.serve('npm start', {
149+
port: 3000,
150+
hostname: request.headers.get('host'),
151+
ready: 'Server listening',
152+
timeout: 60000
153+
});
154+
155+
console.log(`Server accessible at ${url}`);
156+
```
157+
</TypeScriptExample>
158+
159+
### `process.waitFor()`
160+
161+
Wait for a condition to be met for a running process.
162+
163+
```ts
164+
const result = await process.waitFor(condition: ReadyCondition, timeout?: number): Promise<WaitForResult>
165+
```
166+
167+
**Parameters**:
168+
- `condition` - Condition to wait for:
169+
- `string` - Wait for this substring in stdout/stderr
170+
- `RegExp` - Wait for this pattern in logs
171+
- `number` - Wait for this port to accept connections
172+
- `timeout` - Timeout in milliseconds (default: 30000)
173+
174+
**Returns**: `Promise<WaitForResult>` with optional `line` and `match` properties
175+
176+
<TypeScriptExample>
177+
```
178+
const server = await sandbox.startProcess('npm start');
179+
180+
// Wait for log pattern
181+
await server.waitFor('Server listening on port 3000');
182+
183+
// Wait for port
184+
await server.waitFor(3000);
185+
186+
// Wait with regex
187+
const result = await server.waitFor(/Port: (\d+)/);
188+
console.log('Matched:', result.line);
189+
console.log('Port:', result.match?.[1]);
111190
```
112191
</TypeScriptExample>
113192

@@ -116,7 +195,7 @@ const app = await sandbox.startProcess('node app.js', {
116195
List all running processes.
117196

118197
```ts
119-
const processes = await sandbox.listProcesses(): Promise<ProcessInfo[]>
198+
const processes = await sandbox.listProcesses(): Promise<Process[]>
120199
```
121200

122201
<TypeScriptExample>

src/content/docs/sandbox/guides/background-processes.mdx

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,123 @@ console.log('API server started');
6464
```
6565
</TypeScriptExample>
6666

67+
## Wait for process readiness
68+
69+
Wait for processes to become ready before proceeding. This is essential for coordinating services that depend on each other.
70+
71+
### Wait for log pattern
72+
73+
Block until a specific pattern appears in the process output:
74+
75+
<TypeScriptExample>
76+
```
77+
// Wait inline when starting the process (recommended)
78+
const server = await sandbox.startProcess('npm start', {
79+
ready: 'Server listening on port 3000',
80+
readyTimeout: 30000
81+
});
82+
83+
// Server is now ready to accept connections
84+
console.log('Server ready');
85+
```
86+
</TypeScriptExample>
87+
88+
You can also wait after starting the process:
89+
90+
<TypeScriptExample>
91+
```
92+
const server = await sandbox.startProcess('npm start');
93+
94+
// Wait for specific log message
95+
await server.waitFor('Server listening on port 3000');
96+
97+
console.log('Server ready');
98+
```
99+
</TypeScriptExample>
100+
101+
### Wait for port availability
102+
103+
Wait for a port to become available:
104+
105+
<TypeScriptExample>
106+
```
107+
const server = await sandbox.startProcess('node server.js');
108+
109+
// Wait for port to be ready
110+
await server.waitFor(8080);
111+
112+
console.log('Port 8080 is accepting connections');
113+
```
114+
</TypeScriptExample>
115+
116+
### Wait with regex patterns
117+
118+
Use regex to capture information from logs:
119+
120+
<TypeScriptExample>
121+
```
122+
const server = await sandbox.startProcess('npm start', {
123+
ready: /Server listening on port (\d+)/
124+
});
125+
126+
// Get the full logs to extract the port
127+
const logs = await sandbox.getProcessLogs(server.id);
128+
const match = logs.stdout.match(/Server listening on port (\d+)/);
129+
const port = match ? match[1] : null;
130+
131+
console.log(`Server ready on port ${port}`);
132+
```
133+
</TypeScriptExample>
134+
135+
### Start and expose a server
136+
137+
Use `serve()` to start a process, wait for it to be ready, and expose it with a preview URL in one call:
138+
139+
<TypeScriptExample>
140+
```
141+
// Simple usage - wait for port to be ready
142+
const url = await sandbox.serve('npm start', 3000);
143+
144+
// With hostname and readiness pattern
145+
const { url, process } = await sandbox.serve('npm start', {
146+
port: 3000,
147+
hostname: request.headers.get('host'),
148+
ready: 'Server listening',
149+
timeout: 60000
150+
});
151+
152+
console.log(`Server ready at ${url}`);
153+
```
154+
</TypeScriptExample>
155+
156+
### Error handling
157+
158+
Process readiness errors provide detailed context:
159+
160+
<TypeScriptExample>
161+
```
162+
import { ProcessReadyTimeoutError, ProcessExitedBeforeReadyError } from '@cloudflare/sandbox';
163+
164+
try {
165+
const server = await sandbox.startProcess('npm start', {
166+
ready: 'Server listening',
167+
readyTimeout: 30000
168+
});
169+
} catch (error) {
170+
if (error instanceof ProcessReadyTimeoutError) {
171+
console.error('Timeout waiting for server:', error.message);
172+
console.error('Last stdout:', error.stdout);
173+
console.error('Last stderr:', error.stderr);
174+
} else if (error instanceof ProcessExitedBeforeReadyError) {
175+
console.error('Process exited before ready:', error.message);
176+
console.error('Exit code:', error.exitCode);
177+
console.error('Stdout:', error.stdout);
178+
console.error('Stderr:', error.stderr);
179+
}
180+
}
181+
```
182+
</TypeScriptExample>
183+
67184
## Monitor process status
68185

69186
List and check running processes:
@@ -137,28 +254,35 @@ Start services in sequence, waiting for dependencies:
137254

138255
<TypeScriptExample>
139256
```
140-
import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
141-
142-
// Start database first
143-
const db = await sandbox.startProcess('redis-server');
144-
145-
// Wait for database to be ready
146-
const dbLogs = await sandbox.streamProcessLogs(db.id);
147-
for await (const log of parseSSEStream<LogEvent>(dbLogs)) {
148-
if (log.data.includes('Ready to accept connections')) {
149-
break;
150-
}
151-
}
257+
// Start database and wait for it to be ready
258+
const db = await sandbox.startProcess('redis-server', {
259+
ready: 'Ready to accept connections'
260+
});
152261
153262
// Now start API server (depends on database)
154263
const api = await sandbox.startProcess('node api-server.js', {
155-
env: { DATABASE_URL: 'redis://localhost:6379' }
264+
env: { DATABASE_URL: 'redis://localhost:6379' },
265+
ready: 'API server listening'
156266
});
157267
158268
console.log('All services running');
159269
```
160270
</TypeScriptExample>
161271

272+
You can also wait for multiple conditions sequentially:
273+
274+
<TypeScriptExample>
275+
```
276+
const db = await sandbox.startProcess('postgres -D /data');
277+
278+
// Wait for multiple startup phases
279+
await db.waitFor('database system is ready to accept connections');
280+
await db.waitFor(5432); // Wait for port to be available
281+
282+
console.log('Database fully initialized');
283+
```
284+
</TypeScriptExample>
285+
162286
## Keep containers alive for long-running processes
163287

164288
By default, containers automatically shut down after 10 minutes of inactivity. For long-running processes that may have idle periods (like CI/CD pipelines, batch jobs, or monitoring tasks), use the [`keepAlive` option](/sandbox/configuration/sandbox-options/#keepalive):
@@ -207,9 +331,9 @@ When using `keepAlive: true`, containers will not automatically timeout. You **m
207331

208332
## Best practices
209333

210-
- **Wait for readiness** - Stream logs to detect when services are ready
334+
- **Wait for readiness** - Use the `ready` option or `waitFor()` method to ensure services are ready before proceeding
211335
- **Clean up** - Always stop processes when done
212-
- **Handle failures** - Monitor logs for errors and restart if needed
336+
- **Handle failures** - Catch `ProcessReadyTimeoutError` and `ProcessExitedBeforeReadyError` to handle startup issues
213337
- **Use try/finally** - Ensure cleanup happens even on errors
214338
- **Use `keepAlive` for long-running tasks** - Prevent container shutdown during processes with idle periods
215339

0 commit comments

Comments
 (0)