|
|
package ratelimiter
import ( "errors" "time" )
const ( GC_SIZE int = 100 GC_PERIOD time.Duration = 60 * time.Second )
type Memory struct { store map[string]LeakyBucket lastGCCollected time.Time }
func NewMemory() *Memory { m := new(Memory) m.store = make(map[string]LeakyBucket) m.lastGCCollected = time.Now() return m }
func (m *Memory) GetBucketFor(key string) (*LeakyBucket, error) {
bucket, ok := m.store[key] if !ok { return nil, errors.New("miss") }
return &bucket, nil }
func (m *Memory) SetBucketFor(key string, bucket LeakyBucket) error {
if len(m.store) > GC_SIZE { m.GarbageCollect() }
m.store[key] = bucket
return nil }
func (m *Memory) GarbageCollect() { now := time.Now()
// rate limit GC to once per minute
if now.Unix() >= m.lastGCCollected.Add(GC_PERIOD).Unix() { for key, bucket := range m.store { // if the bucket is drained, then GC
if bucket.DrainedAt().Unix() < now.Unix() { delete(m.store, key) } }
m.lastGCCollected = now } }
|