User Tools

Site Tools


Very simple rate limiter

limiter.go
/*
 * Copyright:  Oleg Borodin <onborodin@gmail.com>
 */
 
package main
 
import (
    "fmt"
    "time"
)
 
func main() {
    limiter := NewLimiter(1, 1)
 
    timer := time.NewTicker(1 * time.Millisecond)
    for _ = range timer.C {
        timestamp := time.Now().UnixNano()
        value, passed := limiter.Pass(timestamp)
        if passed {
            fmt.Println(value)
        }
    }
}
 
type Limiter struct {
    timestamp   int64
    period      float64
    rate        float64
    counter     int64
}
 
func NewLimiter(rate float64, period float64) *Limiter {
    timestamp := time.Now().Unix()
    return &Limiter{
        timestamp:  timestamp,
        period:     period,
        rate:       rate/period,
    }
}
 
func (this *Limiter) Pass(value interface{}) (interface{}, bool) {
    var passed bool = false
    now := int64(time.Now().Unix())
 
    if float64(now - this.timestamp) > this.period {
        passed          = true
        this.timestamp  = now
        this.counter    = 1
        return value, passed
    }
    rate := float64(this.counter) / this.period
 
    if rate < this.rate {
        passed = true
    }
    this.counter += 1
    return value, passed
}

Output

$ go run limiter.go
1618903747256014839
1618903749000555314
1618903751000182665