| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 | 
							- package common
 
- import (
 
- 	"sync"
 
- 	"time"
 
- )
 
- type InMemoryRateLimiter struct {
 
- 	store              map[string]*[]int64
 
- 	mutex              sync.Mutex
 
- 	expirationDuration time.Duration
 
- }
 
- func (l *InMemoryRateLimiter) Init(expirationDuration time.Duration) {
 
- 	if l.store == nil {
 
- 		l.mutex.Lock()
 
- 		if l.store == nil {
 
- 			l.store = make(map[string]*[]int64)
 
- 			l.expirationDuration = expirationDuration
 
- 			if expirationDuration > 0 {
 
- 				go l.clearExpiredItems()
 
- 			}
 
- 		}
 
- 		l.mutex.Unlock()
 
- 	}
 
- }
 
- func (l *InMemoryRateLimiter) clearExpiredItems() {
 
- 	for {
 
- 		time.Sleep(l.expirationDuration)
 
- 		l.mutex.Lock()
 
- 		now := time.Now().Unix()
 
- 		for key := range l.store {
 
- 			queue := l.store[key]
 
- 			size := len(*queue)
 
- 			if size == 0 || now-(*queue)[size-1] > int64(l.expirationDuration.Seconds()) {
 
- 				delete(l.store, key)
 
- 			}
 
- 		}
 
- 		l.mutex.Unlock()
 
- 	}
 
- }
 
- // Request parameter duration's unit is seconds
 
- func (l *InMemoryRateLimiter) Request(key string, maxRequestNum int, duration int64) bool {
 
- 	l.mutex.Lock()
 
- 	defer l.mutex.Unlock()
 
- 	// [old <-- new]
 
- 	queue, ok := l.store[key]
 
- 	now := time.Now().Unix()
 
- 	if ok {
 
- 		if len(*queue) < maxRequestNum {
 
- 			*queue = append(*queue, now)
 
- 			return true
 
- 		} else {
 
- 			if now-(*queue)[0] >= duration {
 
- 				*queue = (*queue)[1:]
 
- 				*queue = append(*queue, now)
 
- 				return true
 
- 			} else {
 
- 				return false
 
- 			}
 
- 		}
 
- 	} else {
 
- 		s := make([]int64, 0, maxRequestNum)
 
- 		l.store[key] = &s
 
- 		*(l.store[key]) = append(*(l.store[key]), now)
 
- 	}
 
- 	return true
 
- }
 
 
  |