package pool import ( "code.squareroundforest.org/arpio/times" "time" ) type maxTimeout struct { clock times.Clock max int to time.Duration items []time.Time lastPut int } func makeMaxTimeout(max int, to time.Duration) *maxTimeout { return &maxTimeout{ max: max, to: to, } } func (a *maxTimeout) setClock(c times.Clock) { a.clock = c } func (a *maxTimeout) Target(s Stats) (int, time.Duration) { if a.max <= 0 && a.to <= 0 { return s.Idle, 0 } if a.max > 0 && a.to <= 0 { t := s.Idle if t > a.max { t = a.max } return t, 0 } var zero time.Time if len(a.items) > s.Idle { for i := s.Idle; i < len(a.items); i++ { a.items[i] = zero } a.items = a.items[:s.Idle] if len(a.items) == 0 { a.items = nil } } now := a.clock.Now() for len(a.items) < s.Idle { a.items = append(a.items, now) } puts := s.Put - a.lastPut if puts > 0 && len(a.items) >= puts { a.lastPut = s.Put for i := len(a.items) - puts; i < len(a.items); i++ { a.items[i] = now } } var drop int for drop < len(a.items) && a.items[drop].Add(a.to).Before(now) { a.items[drop] = zero drop++ } if drop > 0 { a.items = a.items[drop:] } if len(a.items) == 0 { a.items = nil return 0, 0 } t := len(a.items) if a.max > 0 && t > a.max { t = a.max } return t, a.items[0].Add(a.to).Sub(now) } func (a *maxTimeout) Load(n int) { if a.to <= 0 { return } now := a.clock.Now() for i := 0; i < n; i++ { a.items = append(a.items, now) } }