123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- // bucket_manager.go
- package golimiter
- import (
- "sync"
- "time"
- "fmt"
- )
- // TokenBucketManager manages multiple token buckets.
- type TokenBucketManager struct {
- tokenBuckets map[string]*TokenBucket // Map of IP addresses to their corresponding token buckets
- mu sync.Mutex // Mutex for synchronization
- }
- // NewTokenBucketManager creates a new TokenBucketManager instance.
- func NewTokenBucketManager() *TokenBucketManager {
- return &TokenBucketManager{
- tokenBuckets: make(map[string]*TokenBucket),
- }
- }
- // GetTokenBucket checks whether a TokenBucket exists for the specified IP address.
- // If a bucket exists and is still valid, it returns the corresponding TokenBucket; otherwise, it returns nil.
- func (tm *TokenBucketManager) GetTokenBucket(ip string) *TokenBucket {
- tm.mu.Lock()
- defer tm.mu.Unlock()
- tb, exists := tm.tokenBuckets[ip]
- if exists {
- if tb.expirationTime.Before(time.Now()) {
- delete(tm.tokenBuckets, ip) // Remove expired bucket from the map
- return nil
- }
- return tb
- }
- return nil
- }
- // CreateTokenBucket creates a new TokenBucket for the given IP address and stores it in the manager.
- // If a bucket already exists, it returns an error.
- func (tm *TokenBucketManager) CreateTokenBucket(ip string, capacity, fillRate int, bucketLifetime time.Duration) (*TokenBucket, error) {
- tm.mu.Lock()
- defer tm.mu.Unlock()
- if _, exists := tm.tokenBuckets[ip]; exists {
- return nil, fmt.Errorf("token bucket for IP %s already exists", ip)
- }
- tb := NewTokenBucket(capacity, fillRate, bucketLifetime)
- tm.tokenBuckets[ip] = tb
- return tb, nil
- }
- // GetRemainingTokens returns the remaining token count for the specified IP address.
- // Returns -1 if the bucket does not exist.
- func (tm *TokenBucketManager) GetRemainingTokens(ip string) int {
- tb := tm.GetTokenBucket(ip)
- if tb == nil {
- return -1
- }
- tb.mu.Lock()
- defer tb.mu.Unlock()
- tb.AddTokensToBucket()
- return tb.tokens
- }
- // cleanupExpiredTokenBuckets removes expired token buckets from the manager.
- func (tm *TokenBucketManager) cleanupExpiredTokenBuckets() {
- tm.mu.Lock()
- defer tm.mu.Unlock()
- currentTime := time.Now()
- for ip, tb := range tm.tokenBuckets {
- if tb.expirationTime.Before(currentTime) {
- delete(tm.tokenBuckets, ip)
- }
- }
- }
- // StartCleanupTask starts a periodic task to clean up expired token buckets at a specified interval.
- func (tm *TokenBucketManager) StartCleanupTask(cleanupInterval time.Duration) {
- ticker := time.NewTicker(cleanupInterval)
- defer ticker.Stop()
- for {
- select {
- case <-ticker.C:
- tm.cleanupExpiredTokenBuckets()
- }
- }
- }
|