Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 105 additions & 2 deletions src/content/docs/sandbox/api/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ for await (const event of parseSSEStream<ExecEvent>(stream)) {
Start a long-running background process.

```ts
const process = await sandbox.startProcess(command: string, options?: ProcessOptions): Promise<ProcessInfo>
const process = await sandbox.startProcess(command: string, options?: ProcessOptions): Promise<Process>
```

**Parameters**:
Expand All @@ -96,7 +96,16 @@ const process = await sandbox.startProcess(command: string, options?: ProcessOpt
- `cwd` - Working directory
- `env` - Environment variables

**Returns**: `Promise<ProcessInfo>` with `id`, `pid`, `command`, `status`
**Returns**: `Promise<Process>` object with:
- `id` - Unique process identifier
- `pid` - System process ID
- `command` - The command being executed
- `status` - Current status (`'running'`, `'exited'`, etc.)
- `kill()` - Stop the process
- `getStatus()` - Get current status
- `getLogs()` - Get accumulated logs
- `waitForPort()` - Wait for process to listen on a port
- `waitForLog()` - Wait for pattern in process output

<TypeScriptExample>
```
Expand Down Expand Up @@ -213,6 +222,100 @@ console.log('Server logs:', logs);
```
</TypeScriptExample>

## Process readiness methods

The `Process` object returned by `startProcess()` includes methods to wait for the process to be ready before proceeding.

### `process.waitForPort()`

Wait for a process to listen on a port.

```ts
await process.waitForPort(port: number, options?: WaitForPortOptions): Promise<void>
```

**Parameters**:
- `port` - The port number to check
- `options` (optional):
- `mode` - Check mode: `'http'` (default) or `'tcp'`
- `timeout` - Maximum wait time in milliseconds
- `interval` - Check interval in milliseconds (default: `100`)
- `path` - HTTP path to check (default: `'/'`, HTTP mode only)
- `status` - Expected HTTP status range (default: `{ min: 200, max: 399 }`, HTTP mode only)

**HTTP mode** (default) makes an HTTP GET request and checks the response status:

<TypeScriptExample>
```
const server = await sandbox.startProcess('node server.js');

// Wait for server to be ready (HTTP mode)
await server.waitForPort(3000);

// Check specific endpoint and status
await server.waitForPort(8080, {
path: '/health',
status: { min: 200, max: 299 },
timeout: 30000
});
```
</TypeScriptExample>

**TCP mode** checks if the port accepts connections:

<TypeScriptExample>
```
const db = await sandbox.startProcess('redis-server');

// Wait for database to accept connections
await db.waitForPort(6379, {
mode: 'tcp',
timeout: 10000
});
```
</TypeScriptExample>

**Throws**:
- `ProcessReadyTimeoutError` - If port does not become ready within timeout
- `ProcessExitedBeforeReadyError` - If process exits before becoming ready

### `process.waitForLog()`

Wait for a pattern to appear in process output.

```ts
const result = await process.waitForLog(pattern: string | RegExp, timeout?: number): Promise<WaitForLogResult>
```

**Parameters**:
- `pattern` - String or RegExp to match in stdout/stderr
- `timeout` - Maximum wait time in milliseconds (optional)

**Returns**: `Promise<WaitForLogResult>` with:
- `line` - The matching line of output
- `matches` - Array of capture groups (for RegExp patterns)

<TypeScriptExample>
```
const server = await sandbox.startProcess('node server.js');

// Wait for string pattern
const result = await server.waitForLog('Server listening');
console.log('Ready:', result.line);

// Wait for RegExp with capture groups
const result = await server.waitForLog(/Server listening on port (\d+)/);
console.log('Port:', result.matches[1]); // Extracted port number

// With timeout
await server.waitForLog('Ready', 30000);
```
</TypeScriptExample>

**Throws**:
- `ProcessReadyTimeoutError` - If pattern is not found within timeout
- `ProcessExitedBeforeReadyError` - If process exits before pattern appears

## Related resources

- [Background processes guide](/sandbox/guides/background-processes/) - Managing long-running processes
Expand Down
48 changes: 33 additions & 15 deletions src/content/docs/sandbox/guides/background-processes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,36 @@ const isRunning = processes.some(p => p.id === processId && p.status === 'runnin
```
</TypeScriptExample>

## Wait for process readiness

Wait for a process to be ready before proceeding:

<TypeScriptExample>
```
const server = await sandbox.startProcess('node server.js');

// Wait for server to respond on port 3000
await server.waitForPort(3000);

console.log('Server is ready');
```
</TypeScriptExample>

Or wait for specific log patterns:

<TypeScriptExample>
```
const server = await sandbox.startProcess('node server.js');

// Wait for log message
const result = await server.waitForLog('Server listening');
console.log('Server is ready:', result.line);
```
</TypeScriptExample>

## Monitor process logs

Stream logs in real-time to detect when a service is ready:
Stream logs in real-time:

<TypeScriptExample>
```
Expand All @@ -98,11 +125,6 @@ const logStream = await sandbox.streamProcessLogs(server.id);

for await (const log of parseSSEStream<LogEvent>(logStream)) {
console.log(log.data);

if (log.data.includes('Server listening')) {
console.log('Server is ready!');
break;
}
}
```
</TypeScriptExample>
Expand Down Expand Up @@ -137,24 +159,20 @@ Start services in sequence, waiting for dependencies:

<TypeScriptExample>
```
import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';

// Start database first
const db = await sandbox.startProcess('redis-server');

// Wait for database to be ready
const dbLogs = await sandbox.streamProcessLogs(db.id);
for await (const log of parseSSEStream<LogEvent>(dbLogs)) {
if (log.data.includes('Ready to accept connections')) {
break;
}
}
await db.waitForPort(6379, { mode: 'tcp' });

// Now start API server (depends on database)
const api = await sandbox.startProcess('node api-server.js', {
env: { DATABASE_URL: 'redis://localhost:6379' }
});

// Wait for API to be ready
await api.waitForPort(8080, { path: '/health' });

console.log('All services running');
```
</TypeScriptExample>
Expand Down Expand Up @@ -207,7 +225,7 @@ When using `keepAlive: true`, containers will not automatically timeout. You **m

## Best practices

- **Wait for readiness** - Stream logs to detect when services are ready
- **Wait for readiness** - Use `waitForPort()` or `waitForLog()` to detect when services are ready
- **Clean up** - Always stop processes when done
- **Handle failures** - Monitor logs for errors and restart if needed
- **Use try/finally** - Ensure cleanup happens even on errors
Expand Down
Loading