package account import ( "context" "ds2api/internal/config" ) func (p *Pool) Acquire(target string, exclude map[string]bool) (config.Account, bool) { p.mu.Lock() defer p.mu.Unlock() return p.acquireLocked(target, normalizeExclude(exclude)) } func (p *Pool) AcquireWait(ctx context.Context, target string, exclude map[string]bool) (config.Account, bool) { if ctx == nil { ctx = context.Background() } exclude = normalizeExclude(exclude) for { if ctx.Err() != nil { return config.Account{}, false } p.mu.Lock() if acc, ok := p.acquireLocked(target, exclude); ok { p.mu.Unlock() return acc, true } if !p.canQueueLocked(target, exclude) { p.mu.Unlock() return config.Account{}, false } waiter := make(chan struct{}) p.waiters = append(p.waiters, waiter) p.mu.Unlock() select { case <-ctx.Done(): p.mu.Lock() p.removeWaiterLocked(waiter) p.mu.Unlock() return config.Account{}, false case <-waiter: } } } func (p *Pool) acquireLocked(target string, exclude map[string]bool) (config.Account, bool) { if target != "" { if exclude[target] || !p.canAcquireIDLocked(target) { return config.Account{}, false } acc, ok := p.store.FindAccount(target) if !ok { return config.Account{}, false } p.inUse[target]++ p.bumpQueue(target) return acc, true } return p.tryAcquire(exclude) } func (p *Pool) tryAcquire(exclude map[string]bool) (config.Account, bool) { for i := 0; i < len(p.queue); i++ { id := p.queue[i] if exclude[id] || !p.canAcquireIDLocked(id) { continue } acc, ok := p.store.FindAccount(id) if !ok { continue } p.inUse[id]++ p.bumpQueue(id) return acc, true } return config.Account{}, false } func (p *Pool) bumpQueue(accountID string) { for i, id := range p.queue { if id != accountID { continue } p.queue = append(p.queue[:i], p.queue[i+1:]...) p.queue = append(p.queue, accountID) return } } func normalizeExclude(exclude map[string]bool) map[string]bool { if exclude == nil { return map[string]bool{} } return exclude }