package ratelimit import ( "context" "sync" "time" ) type Limiter struct { interval time.Duration mu sync.Mutex next time.Time } func New(requestsPerMinute int) *Limiter { if requestsPerMinute <= 0 { return &Limiter{} } return &Limiter{interval: time.Minute / time.Duration(requestsPerMinute)} } func (l *Limiter) Wait(ctx context.Context) error { if l.interval <= 0 { return nil } l.mu.Lock() now := time.Now() if l.next.IsZero() { l.next = now.Add(l.interval) l.mu.Unlock() return nil } wake := l.next if now.After(wake) { l.next = now.Add(l.interval) l.mu.Unlock() return nil } l.next = l.next.Add(l.interval) l.mu.Unlock() timer := time.NewTimer(time.Until(wake)) defer timer.Stop() select { case <-ctx.Done(): return ctx.Err() case <-timer.C: return nil } }