Search code examples
gotimerate-limiting

golang rate limit per minute


How to rate limit 20 requests per minute?

import "golang.org/x/time/rate"

limiter := rate.NewLimiter(rate.Every(1*time.Minute), 20)

for {
    limiter.Wait()
    //more code
}

This does not work. What that does is, it allows first 20 requests, then only allows 1 request per minute. What is expected is 20 requests on the first minute(Need not be evenly spread like 1 per 3 seconds) and then 20 more requests on the second minute. At any 1 minute interval, there cannot be more than 20 requests sent.

My solution: https://stackoverflow.com/a/72452542


Solution

  • My solution

    import (
            "sync"
            "time"
    )
    
    type Limiter interface {
            Wait()
    }
    
    type limiter struct {
            tick    time.Duration
            count   uint
            entries []time.Time
            index   uint
            mutex   sync.Mutex
    }
    
    func NewLimiter(tick time.Duration, count uint) Limiter {
            l := limiter{
                    tick:  tick,
                    count: count,
                    index: 0,
            }
            l.entries = make([]time.Time, count)
            before := time.Now().Add(-2 * tick)
            for i, _ := range l.entries {
                    l.entries[i] = before
            }
            return &l
    }
    func (l *limiter) Wait() {
            l.mutex.Lock()
            defer l.mutex.Unlock()
            last := &l.entries[l.index]
            next := last.Add(l.tick)
            now := time.Now()
            if now.Before(next) {
                    time.Sleep(next.Sub(now))
            }
            *last = time.Now()
            l.index = l.index + 1
            if l.index == l.count {
                    l.index = 0
            }
    }