Refactor container file operations for improved performance

- Update ReadFile method to read directly from the host's bind-mounted workspace instead of using Docker's CopyFromContainer, enhancing performance.
- Introduce containerPathToHost method to convert container paths to host paths, ensuring proper access to bind-mounted directories.
- Simplify idle container cleanup logic by storing the idle time in a variable for better readability.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Max 2026-02-01 11:24:47 +08:00
parent 2e94ce5062
commit d78b4ea54a

View file

@ -648,8 +648,10 @@ func (m *Manager) Cleanup(ctx context.Context) error {
name := key.(string)
c := value.(*Container)
idleTime := now.Sub(c.LastUsedAt)
// Stop idle containers
if c.Status == StatusRunning && now.Sub(c.LastUsedAt) > m.config.IdleTimeout {
if c.Status == StatusRunning && idleTime > m.config.IdleTimeout {
m.Stop(ctx, name)
}
@ -727,6 +729,7 @@ func (m *Manager) WriteFile(ctx context.Context, name, path string, content []by
}
// ReadFile reads content from a file in container
// Since workspace is bind-mounted, we read directly from host for better performance
func (m *Manager) ReadFile(ctx context.Context, name, path string) ([]byte, error) {
c, ok := m.containers.Load(name)
if !ok {
@ -734,20 +737,13 @@ func (m *Manager) ReadFile(ctx context.Context, name, path string) ([]byte, erro
}
cont := c.(*Container)
reader, _, err := m.dockerClient.CopyFromContainer(ctx, cont.ID, path)
if err != nil {
return nil, err
}
defer reader.Close()
// Extract from tar
tr := tar.NewReader(reader)
_, err = tr.Next()
if err != nil {
return nil, err
// Read directly from host bind mount
hostPath := m.containerPathToHost(cont, path)
if hostPath == "" {
return nil, fmt.Errorf("path %s is not within workspace", path)
}
return io.ReadAll(tr)
return os.ReadFile(hostPath)
}
// ListDir lists directory contents in container
@ -840,6 +836,20 @@ func (m *Manager) ensureIPCSession(ctx context.Context, userID, chatID string) {
m.ipcManager.Create(ctx, sessionID, agentCtx, nil)
}
// containerPathToHost converts a container path to the corresponding host path
// Returns empty string if the path is not within a bind-mounted directory
func (m *Manager) containerPathToHost(cont *Container, containerPath string) string {
// Container workspace is mounted at ContainerWorkDir (e.g., /workspace)
// Host path is WorkspaceRoot/{userID}/{chatID}
workDir := m.config.ContainerWorkDir
if strings.HasPrefix(containerPath, workDir) {
relativePath := strings.TrimPrefix(containerPath, workDir)
relativePath = strings.TrimPrefix(relativePath, "/")
return filepath.Join(m.config.WorkspaceRoot, cont.UserID, cont.ChatID, relativePath)
}
return ""
}
// fixIPCSocketPermissions fixes IPC socket permissions inside the container
// This is needed because macOS Docker Desktop with gRPC-FUSE doesn't properly
// preserve Unix socket permissions when bind mounting from host.