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:
parent
2e94ce5062
commit
d78b4ea54a
1 changed files with 23 additions and 13 deletions
|
|
@ -648,8 +648,10 @@ func (m *Manager) Cleanup(ctx context.Context) error {
|
||||||
name := key.(string)
|
name := key.(string)
|
||||||
c := value.(*Container)
|
c := value.(*Container)
|
||||||
|
|
||||||
|
idleTime := now.Sub(c.LastUsedAt)
|
||||||
|
|
||||||
// Stop idle containers
|
// 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)
|
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
|
// 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) {
|
func (m *Manager) ReadFile(ctx context.Context, name, path string) ([]byte, error) {
|
||||||
c, ok := m.containers.Load(name)
|
c, ok := m.containers.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -734,20 +737,13 @@ func (m *Manager) ReadFile(ctx context.Context, name, path string) ([]byte, erro
|
||||||
}
|
}
|
||||||
cont := c.(*Container)
|
cont := c.(*Container)
|
||||||
|
|
||||||
reader, _, err := m.dockerClient.CopyFromContainer(ctx, cont.ID, path)
|
// Read directly from host bind mount
|
||||||
if err != nil {
|
hostPath := m.containerPathToHost(cont, path)
|
||||||
return nil, err
|
if hostPath == "" {
|
||||||
}
|
return nil, fmt.Errorf("path %s is not within workspace", path)
|
||||||
defer reader.Close()
|
|
||||||
|
|
||||||
// Extract from tar
|
|
||||||
tr := tar.NewReader(reader)
|
|
||||||
_, err = tr.Next()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return io.ReadAll(tr)
|
return os.ReadFile(hostPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListDir lists directory contents in container
|
// 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)
|
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
|
// fixIPCSocketPermissions fixes IPC socket permissions inside the container
|
||||||
// This is needed because macOS Docker Desktop with gRPC-FUSE doesn't properly
|
// This is needed because macOS Docker Desktop with gRPC-FUSE doesn't properly
|
||||||
// preserve Unix socket permissions when bind mounting from host.
|
// preserve Unix socket permissions when bind mounting from host.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue