Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191
This commit is contained in:
291
OPENCODE_PROCESS_MANAGER.md
Normal file
291
OPENCODE_PROCESS_MANAGER.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# OpenCode Process Manager
|
||||
|
||||
## Overview
|
||||
|
||||
This document explains the OpenCode Process Manager implementation, which optimizes resource usage by managing OpenCode sessions through a singleton instance manager.
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Previously, the application spawned a **new OpenCode process for every message** sent by users. This meant:
|
||||
- Multiple concurrent sessions resulted in dozens of separate OpenCode processes
|
||||
- High memory and CPU overhead from process spawning
|
||||
- No process reuse or pooling
|
||||
- Inefficient resource utilization
|
||||
|
||||
## Solution
|
||||
|
||||
The `OpencodeProcessManager` class provides a singleton manager that:
|
||||
|
||||
1. **Tracks all OpenCode sessions** in a centralized location
|
||||
2. **Monitors process execution** with detailed logging
|
||||
3. **Prepares for future optimization** when OpenCode supports server/daemon mode
|
||||
4. **Falls back gracefully** to per-message spawning when server mode is unavailable
|
||||
|
||||
## Current Implementation
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Multiple User Sessions │
|
||||
│ (Session A, B, C, D...) │
|
||||
└───────────┬─────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ OpencodeProcessManager (Singleton) │
|
||||
│ - Tracks all sessions │
|
||||
│ - Monitors execution │
|
||||
│ - Manages process lifecycle │
|
||||
└───────────┬─────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ OpenCode CLI Execution │
|
||||
│ (Currently: per-message processes) │
|
||||
│ (Future: single daemon instance) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Features
|
||||
|
||||
1. **Singleton Pattern**: Only one `OpencodeProcessManager` instance exists across the entire application
|
||||
2. **Session Tracking**: Maps session IDs to their workspace directories
|
||||
3. **Process Monitoring**: Logs execution time, active processes, and resource usage
|
||||
4. **Graceful Degradation**: Falls back to per-message spawning if server mode unavailable
|
||||
5. **Lifecycle Management**: Properly initialized on startup and cleaned up on shutdown
|
||||
|
||||
### Code Locations
|
||||
|
||||
- **Manager Class**: Lines ~575-836 in [server.js](chat/server.js)
|
||||
- **Singleton Instance**: Line ~838 in [server.js](chat/server.js)
|
||||
- **Integration**: Line ~6165 in [server.js](chat/server.js) (sendToOpencode function)
|
||||
- **Initialization**: Lines ~11239-11246 in [server.js](chat/server.js) (bootstrap function)
|
||||
- **Shutdown**: Line ~981 in [server.js](chat/server.js) (gracefulShutdown function)
|
||||
- **Status Endpoint**: Lines ~9832-9867 in [server.js](chat/server.js)
|
||||
|
||||
## Current Behavior
|
||||
|
||||
### What Happens Now
|
||||
|
||||
Since OpenCode doesn't currently support a persistent server/daemon mode, the manager:
|
||||
|
||||
1. **Tracks each execution** with detailed logging
|
||||
2. **Reports statistics** via the `/api/opencode/status` endpoint
|
||||
3. **Routes through `executeStandalone`** which spawns per-message processes
|
||||
4. **Logs process lifecycle** (start, duration, completion)
|
||||
|
||||
This provides:
|
||||
- ✅ Better visibility into OpenCode usage
|
||||
- ✅ Centralized execution management
|
||||
- ✅ Foundation for future optimization
|
||||
- ⚠️ Still spawns separate processes per message (but tracked)
|
||||
|
||||
## Future Optimization
|
||||
|
||||
### When OpenCode Adds Server Mode
|
||||
|
||||
If/when OpenCode supports a persistent server/daemon mode (e.g., `opencode serve` or `opencode daemon`):
|
||||
|
||||
1. **Update `getServerModeArgs()`** to return the correct command arguments
|
||||
2. **The manager will automatically**:
|
||||
- Start a single OpenCode process on server startup
|
||||
- Route all sessions through this single instance
|
||||
- Maintain persistent connections
|
||||
- Dramatically reduce resource overhead
|
||||
|
||||
### Expected Benefits (Future)
|
||||
|
||||
When server mode is available:
|
||||
- **90%+ reduction** in process spawning overhead
|
||||
- **Faster response times** (no process startup delay)
|
||||
- **Lower memory usage** (one process vs. many)
|
||||
- **Better session continuity** (persistent state)
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Status Endpoint
|
||||
|
||||
Check OpenCode manager status:
|
||||
```bash
|
||||
curl http://localhost:3000/api/opencode/status
|
||||
```
|
||||
|
||||
Response includes:
|
||||
```json
|
||||
{
|
||||
"available": true,
|
||||
"version": "...",
|
||||
"runningProcesses": 3,
|
||||
"activeStreams": 2,
|
||||
"processManager": {
|
||||
"isRunning": false,
|
||||
"isReady": true,
|
||||
"pendingRequests": 0,
|
||||
"activeSessions": 5,
|
||||
"lastActivity": 1234567890,
|
||||
"idleTime": 1234,
|
||||
"mode": "per-session",
|
||||
"description": "Each message spawns separate OpenCode process"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Logging
|
||||
|
||||
The manager logs:
|
||||
- Process execution start/end
|
||||
- Duration of each command
|
||||
- Active process count
|
||||
- Session workspace mapping
|
||||
- Errors and failures
|
||||
|
||||
Look for log entries with:
|
||||
- `"OpenCode process manager..."`
|
||||
- `"Executing OpenCode command (standalone)"`
|
||||
- `"OpenCode command completed"`
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### OpencodeProcessManager Class
|
||||
|
||||
#### Properties
|
||||
- `process`: Reference to the persistent OpenCode process (when in server mode)
|
||||
- `isReady`: Boolean indicating if the manager is ready to accept requests
|
||||
- `pendingRequests`: Map of in-flight requests awaiting responses
|
||||
- `sessionWorkspaces`: Map of session IDs to their workspace directories
|
||||
- `lastActivity`: Timestamp of last activity (for idle detection)
|
||||
- `heartbeatInterval`: Timer for keeping persistent connection alive
|
||||
|
||||
#### Methods
|
||||
|
||||
**`start()`**
|
||||
- Initializes the manager
|
||||
- Attempts to start OpenCode in server mode
|
||||
- Falls back to per-session mode if unavailable
|
||||
|
||||
**`executeInSession(sessionId, workspaceDir, command, args, options)`**
|
||||
- Main execution method
|
||||
- Routes through persistent process (future) or standalone spawning (current)
|
||||
- Tracks session -> workspace mapping
|
||||
|
||||
**`executeStandalone(workspaceDir, command, args, options)`**
|
||||
- Current fallback implementation
|
||||
- Spawns individual OpenCode process
|
||||
- Logs execution metrics
|
||||
|
||||
**`stop()`**
|
||||
- Gracefully shuts down manager
|
||||
- Terminates persistent process if running
|
||||
- Cleans up resources
|
||||
|
||||
**`getStats()`**
|
||||
- Returns current manager statistics
|
||||
- Used by monitoring endpoint
|
||||
|
||||
### Integration Points
|
||||
|
||||
1. **Bootstrap** (startup): Manager initialized after all state is loaded
|
||||
2. **sendToOpencode**: Routes all OpenCode executions through manager
|
||||
3. **gracefulShutdown**: Stops manager before server shutdown
|
||||
4. **Status endpoint**: Exposes manager statistics
|
||||
|
||||
## Testing
|
||||
|
||||
### Verify Installation
|
||||
|
||||
1. Start the server:
|
||||
```bash
|
||||
node chat/server.js
|
||||
```
|
||||
|
||||
2. Check the logs for:
|
||||
```
|
||||
Initializing OpenCode process manager...
|
||||
OpenCode does not support server mode, will use per-session approach
|
||||
OpenCode process manager initialized
|
||||
```
|
||||
|
||||
3. Check status endpoint:
|
||||
```bash
|
||||
curl http://localhost:3000/api/opencode/status | jq .
|
||||
```
|
||||
|
||||
4. Send a message in a session and observe logs:
|
||||
```
|
||||
Executing OpenCode command (standalone) { processId: '...', activeProcesses: 1 }
|
||||
OpenCode command completed { processId: '...', duration: 1234 }
|
||||
```
|
||||
|
||||
### Multiple Concurrent Sessions
|
||||
|
||||
1. Open multiple builder sessions in different browser tabs
|
||||
2. Send messages in each
|
||||
3. Check `/api/opencode/status` to see `runningProcesses` count
|
||||
4. Each process should be logged with start/end times
|
||||
|
||||
## Configuration
|
||||
|
||||
No configuration required. The manager automatically:
|
||||
- Detects if OpenCode supports server mode
|
||||
- Falls back to per-session spawning
|
||||
- Adapts to available capabilities
|
||||
|
||||
## Performance Impact
|
||||
|
||||
### Current (Per-Session Mode)
|
||||
- ✅ Better tracking and visibility
|
||||
- ✅ Centralized management
|
||||
- ✅ Foundation for future optimization
|
||||
- ➖ No performance improvement yet (still spawns separate processes)
|
||||
|
||||
### Future (Server Mode)
|
||||
- ✅ 90%+ reduction in process overhead
|
||||
- ✅ Faster response times
|
||||
- ✅ Lower memory usage
|
||||
- ✅ Better resource utilization
|
||||
|
||||
## Migration Notes
|
||||
|
||||
This change is **backward compatible**:
|
||||
- No changes to session management
|
||||
- No changes to API endpoints (except enhanced status response)
|
||||
- No changes to client behavior
|
||||
- Existing sessions continue to work
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Manager Not Starting
|
||||
Check logs for: `"OpenCode process manager initialization failed"`
|
||||
- This is expected if OpenCode doesn't support server mode
|
||||
- Manager falls back to per-session spawning automatically
|
||||
|
||||
### Multiple Processes Still Running
|
||||
This is **expected behavior** in current mode:
|
||||
- Each message spawns a separate process
|
||||
- This will change when OpenCode adds server mode support
|
||||
- All processes are now tracked and logged
|
||||
|
||||
### Status Endpoint Not Responding
|
||||
1. Verify server is running
|
||||
2. Check that route is registered in `routeInternal()`
|
||||
3. Look for initialization errors in logs
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Add Server Mode Support**: Update `getServerModeArgs()` when available
|
||||
2. **Request Batching**: Queue and batch multiple requests
|
||||
3. **Connection Pooling**: Maintain pool of persistent connections
|
||||
4. **Load Balancing**: Distribute across multiple OpenCode instances
|
||||
5. **Health Checks**: Monitor and restart unresponsive instances
|
||||
|
||||
## Summary
|
||||
|
||||
The OpenCode Process Manager provides:
|
||||
- ✅ Centralized session management
|
||||
- ✅ Comprehensive execution tracking
|
||||
- ✅ Foundation for future optimization
|
||||
- ✅ Graceful fallback to current behavior
|
||||
- ✅ Enhanced monitoring and debugging
|
||||
|
||||
While currently operating in per-session mode, it's ready to leverage OpenCode's server mode as soon as it becomes available, providing significant resource savings and performance improvements.
|
||||
Reference in New Issue
Block a user