// Package backendpool manages runtime capacity independently for each executor backend. package backendpool import "sync" type Pool struct { mu sync.Mutex capacity int active map[string]struct{} } func New(capacity int) *Pool { return &Pool{capacity: capacity, active: make(map[string]struct{})} } // Acquire reserves a backend slot without blocking. Redelivery of the same // assignment is idempotent and succeeds even while the pool is full. func (p *Pool) Acquire(assignmentID string) bool { p.mu.Lock() defer p.mu.Unlock() if _, exists := p.active[assignmentID]; exists { return true } if assignmentID == "" || len(p.active) >= p.capacity { return false } p.active[assignmentID] = struct{}{} return true } func (p *Pool) Restore(assignmentID string) { if assignmentID == "" { return } p.mu.Lock() p.active[assignmentID] = struct{}{} p.mu.Unlock() } func (p *Pool) Release(assignmentID string) { p.mu.Lock() delete(p.active, assignmentID) p.mu.Unlock() } func (p *Pool) Active() int { p.mu.Lock() defer p.mu.Unlock() return len(p.active) }