fix(bugseti): add mutex protection to seeder concurrent access
Add sync.Mutex to SeederService to protect shared state during concurrent SeedIssue, GetWorkspaceDir, and CleanupWorkspace calls. Extract getWorkspaceDir as lock-free helper to avoid double-locking. Closes #63 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
251ce85f20
commit
69b236e5c7
1 changed files with 17 additions and 1 deletions
|
|
@ -11,11 +11,13 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SeederService prepares context for issues using the seed-agent-developer skill.
|
// SeederService prepares context for issues using the seed-agent-developer skill.
|
||||||
type SeederService struct {
|
type SeederService struct {
|
||||||
|
mu sync.Mutex
|
||||||
config *ConfigService
|
config *ConfigService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +35,9 @@ func (s *SeederService) ServiceName() string {
|
||||||
|
|
||||||
// SeedIssue prepares context for an issue by calling the seed-agent-developer skill.
|
// SeedIssue prepares context for an issue by calling the seed-agent-developer skill.
|
||||||
func (s *SeederService) SeedIssue(issue *Issue) (*IssueContext, error) {
|
func (s *SeederService) SeedIssue(issue *Issue) (*IssueContext, error) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
if issue == nil {
|
if issue == nil {
|
||||||
return nil, fmt.Errorf("issue is nil")
|
return nil, fmt.Errorf("issue is nil")
|
||||||
}
|
}
|
||||||
|
|
@ -338,6 +343,14 @@ func sanitizeIssueContext(ctx *IssueContext, guard *EthicsGuard) *IssueContext {
|
||||||
|
|
||||||
// GetWorkspaceDir returns the workspace directory for an issue.
|
// GetWorkspaceDir returns the workspace directory for an issue.
|
||||||
func (s *SeederService) GetWorkspaceDir(issue *Issue) string {
|
func (s *SeederService) GetWorkspaceDir(issue *Issue) string {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
return s.getWorkspaceDir(issue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWorkspaceDir is the lock-free implementation; caller must hold s.mu.
|
||||||
|
func (s *SeederService) getWorkspaceDir(issue *Issue) string {
|
||||||
baseDir := s.config.GetWorkspaceDir()
|
baseDir := s.config.GetWorkspaceDir()
|
||||||
if baseDir == "" {
|
if baseDir == "" {
|
||||||
baseDir = filepath.Join(os.TempDir(), "bugseti")
|
baseDir = filepath.Join(os.TempDir(), "bugseti")
|
||||||
|
|
@ -347,6 +360,9 @@ func (s *SeederService) GetWorkspaceDir(issue *Issue) string {
|
||||||
|
|
||||||
// CleanupWorkspace removes the workspace for an issue.
|
// CleanupWorkspace removes the workspace for an issue.
|
||||||
func (s *SeederService) CleanupWorkspace(issue *Issue) error {
|
func (s *SeederService) CleanupWorkspace(issue *Issue) error {
|
||||||
workDir := s.GetWorkspaceDir(issue)
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
workDir := s.getWorkspaceDir(issue)
|
||||||
return os.RemoveAll(workDir)
|
return os.RemoveAll(workDir)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue