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