Skip to content

Commit cead379

Browse files
Add process readiness documentation
Documents new process readiness features from PR #273: - Process.waitFor() method for waiting on conditions - startProcess() ready/readyTimeout options - serve() method for starting servers with readiness checks Updates: - Commands API reference with new methods and options - Background processes guide with readiness patterns - Examples showing string, regex, and port-based waiting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 1f2b21b commit cead379

File tree

2 files changed

+182
-32
lines changed

2 files changed

+182
-32
lines changed

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

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,24 @@ 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` - Wait for condition before returning (string, RegExp, or port number)
99+
- `readyTimeout` - Timeout for readiness check in milliseconds (default: 30000)
100+
- `onStart`, `onExit`, `onError` - Lifecycle callbacks
98101

99-
**Returns**: `Promise<ProcessInfo>` with `id`, `pid`, `command`, `status`
102+
**Returns**: `Promise<Process>` with methods:
103+
- `id`, `pid`, `command`, `status` - Process information
104+
- `kill()` - Terminate the process
105+
- `getStatus()` - Get current status
106+
- `getLogs()` - Get accumulated logs
107+
- `waitFor(condition, timeout?)` - Wait for a log pattern or port
100108

101109
<TypeScriptExample>
102110
```
@@ -108,6 +116,95 @@ const app = await sandbox.startProcess('node app.js', {
108116
cwd: '/workspace/my-app',
109117
env: { NODE_ENV: 'production', PORT: '3000' }
110118
});
119+
120+
// Wait for process to be ready before continuing
121+
const server = await sandbox.startProcess('npm start', {
122+
ready: 'Server listening on port 3000',
123+
readyTimeout: 30000
124+
});
125+
console.log('Server is ready');
126+
```
127+
</TypeScriptExample>
128+
129+
### `serve()`
130+
131+
Start a server process, wait for it to be ready, and optionally expose it with a preview URL.
132+
133+
```ts
134+
const result = await sandbox.serve(command: string, options: number | ServeOptions): Promise<string | { url: string; process: Process }>
135+
```
136+
137+
**Parameters**:
138+
- `command` - The command to start the server
139+
- `options` - Port number or full options:
140+
- `port` - Port to wait for and expose
141+
- `hostname` - Hostname for preview URL (required for URL generation)
142+
- `ready` - Additional log pattern to wait for (waits for both pattern AND port)
143+
- `timeout` - Timeout in milliseconds (default: 60000)
144+
- `env` - Environment variables
145+
- `cwd` - Working directory
146+
147+
**Returns**:
148+
- If `hostname` provided: `{ url: string; process: Process }` with preview URL
149+
- Otherwise: `string` with localhost URL
150+
151+
<TypeScriptExample>
152+
```
153+
// Simple usage - just wait for port
154+
const url = await sandbox.serve('npm start', 3000);
155+
console.log('Server ready:', url); // http://localhost:3000
156+
157+
// Full usage with preview URL
158+
const { url, process } = await sandbox.serve('npm start', {
159+
port: 3000,
160+
hostname: 'example.com',
161+
ready: /Server listening/, // Wait for both log pattern AND port
162+
timeout: 60000
163+
});
164+
console.log('Server URL:', url);
165+
console.log('Process ID:', process.id);
166+
```
167+
</TypeScriptExample>
168+
169+
### `Process.waitFor()`
170+
171+
Wait for a process to meet a condition (log pattern or port availability).
172+
173+
```ts
174+
const result = await process.waitFor(condition: string | RegExp | number, timeout?: number): Promise<WaitForResult>
175+
```
176+
177+
**Parameters**:
178+
- `condition` - What to wait for:
179+
- `string` - Wait for this substring in stdout/stderr
180+
- `RegExp` - Wait for this pattern (returns capture groups)
181+
- `number` - Wait for this port to accept connections
182+
- `timeout` - Timeout in milliseconds (default: 30000)
183+
184+
**Returns**: `Promise<WaitForResult>` with:
185+
- `line?` - The log line that matched (for string/regex)
186+
- `match?` - Regex capture groups (for regex patterns)
187+
188+
<TypeScriptExample>
189+
```
190+
const proc = await sandbox.startProcess('npm start');
191+
192+
// Wait for log message
193+
await proc.waitFor('Server listening on port 3000');
194+
195+
// Wait for regex pattern with capture groups
196+
const result = await proc.waitFor(/listening on port (\d+)/);
197+
console.log('Port:', result.match[1]); // Captured port number
198+
199+
// Wait for port to be available
200+
await proc.waitFor(3000);
201+
console.log('Port 3000 is accepting connections');
202+
203+
// Multiple conditions
204+
await proc.waitFor('Database connected');
205+
await proc.waitFor('Cache initialized');
206+
await proc.waitFor(8080);
207+
console.log('All services ready');
111208
```
112209
</TypeScriptExample>
113210

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

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -83,36 +83,73 @@ const isRunning = processes.some(p => p.id === processId && p.status === 'runnin
8383
```
8484
</TypeScriptExample>
8585

86-
## Monitor process logs
86+
## Wait for process readiness
8787

88-
Stream logs in real-time to detect when a service is ready:
88+
Wait for processes to be ready before proceeding using inline readiness checks:
8989

9090
<TypeScriptExample>
9191
```
92-
import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
92+
// Wait for log message
93+
const server = await sandbox.startProcess('npm start', {
94+
ready: 'Server listening on port 3000',
95+
readyTimeout: 30000
96+
});
97+
console.log('Server is ready');
9398
94-
const server = await sandbox.startProcess('node server.js');
99+
// Wait for regex pattern
100+
const db = await sandbox.startProcess('redis-server', {
101+
ready: /Ready to accept connections/
102+
});
95103
96-
// Stream logs
97-
const logStream = await sandbox.streamProcessLogs(server.id);
104+
// Wait for port availability
105+
const api = await sandbox.startProcess('node api.js', {
106+
ready: 8080
107+
});
108+
```
109+
</TypeScriptExample>
98110

99-
for await (const log of parseSSEStream<LogEvent>(logStream)) {
100-
console.log(log.data);
111+
Or wait for conditions after starting:
101112

102-
if (log.data.includes('Server listening')) {
103-
console.log('Server is ready!');
104-
break;
105-
}
106-
}
113+
<TypeScriptExample>
114+
```
115+
const proc = await sandbox.startProcess('npm start');
116+
117+
// Wait for specific log message
118+
await proc.waitFor('Database connected');
119+
120+
// Wait for port to be available
121+
await proc.waitFor(3000);
122+
123+
// Wait for regex with capture groups
124+
const result = await proc.waitFor(/listening on port (\d+)/);
125+
console.log('Port:', result.match[1]);
107126
```
108127
</TypeScriptExample>
109128

110-
Or get accumulated logs:
129+
## Monitor process logs
130+
131+
Get accumulated logs from a process:
111132

112133
<TypeScriptExample>
113134
```
114-
const logs = await sandbox.getProcessLogs(server.id);
115-
console.log('Logs:', logs);
135+
const logs = await server.getLogs();
136+
console.log('Stdout:', logs.stdout);
137+
console.log('Stderr:', logs.stderr);
138+
```
139+
</TypeScriptExample>
140+
141+
Or stream logs in real-time for monitoring:
142+
143+
<TypeScriptExample>
144+
```
145+
import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
146+
147+
const server = await sandbox.startProcess('node server.js');
148+
const logStream = await sandbox.streamProcessLogs(server.id);
149+
150+
for await (const log of parseSSEStream<LogEvent>(logStream)) {
151+
console.log(log.data);
152+
}
116153
```
117154
</TypeScriptExample>
118155

@@ -137,28 +174,43 @@ Start services in sequence, waiting for dependencies:
137174

138175
<TypeScriptExample>
139176
```
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-
}
177+
// Start database first and wait for it to be ready
178+
const db = await sandbox.startProcess('redis-server', {
179+
ready: 'Ready to accept connections'
180+
});
152181
153182
// Now start API server (depends on database)
154183
const api = await sandbox.startProcess('node api-server.js', {
155-
env: { DATABASE_URL: 'redis://localhost:6379' }
184+
env: { DATABASE_URL: 'redis://localhost:6379' },
185+
ready: 'API server listening'
156186
});
157187
158188
console.log('All services running');
159189
```
160190
</TypeScriptExample>
161191

192+
## Start and expose a server
193+
194+
Use `serve()` to start a server, wait for it to be ready, and get a preview URL in one call:
195+
196+
<TypeScriptExample>
197+
```
198+
// Simple usage - wait for port
199+
const url = await sandbox.serve('npm start', 3000);
200+
console.log('Server ready at:', url);
201+
202+
// With preview URL
203+
const { url, process } = await sandbox.serve('npm start', {
204+
port: 3000,
205+
hostname: request.headers.get('host'),
206+
ready: /Server listening/ // Optional: also wait for log pattern
207+
});
208+
209+
console.log('Preview URL:', url);
210+
console.log('Process ID:', process.id);
211+
```
212+
</TypeScriptExample>
213+
162214
## Keep containers alive for long-running processes
163215

164216
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,7 +259,8 @@ When using `keepAlive: true`, containers will not automatically timeout. You **m
207259

208260
## Best practices
209261

210-
- **Wait for readiness** - Stream logs to detect when services are ready
262+
- **Wait for readiness** - Use `ready` option or `waitFor()` to ensure services are fully started before proceeding
263+
- **Choose the right pattern** - Use `ready` option for simple cases, `waitFor()` for multiple conditions, or `serve()` for servers
211264
- **Clean up** - Always stop processes when done
212265
- **Handle failures** - Monitor logs for errors and restart if needed
213266
- **Use try/finally** - Ensure cleanup happens even on errors

0 commit comments

Comments
 (0)