golimiter.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // golimiter.go
  2. package golimiter
  3. import (
  4. "sync"
  5. "time"
  6. )
  7. // TokenBucket represents a rate limiting mechanism based on the token bucket algorithm.
  8. type TokenBucket struct {
  9. capacity int // Maximum number of tokens the bucket can hold
  10. tokens int // Current number of tokens in the bucket
  11. fillRate int // Rate at which tokens are added to the bucket (tokens per second)
  12. lastTimestamp time.Time // Timestamp of the last token retrieval or addition
  13. expirationTime time.Time // Time when the bucket will expire and be removed from the manager
  14. mu sync.Mutex // Mutex for synchronization
  15. }
  16. // NewTokenBucket creates a new TokenBucket instance with the specified parameters.
  17. func NewTokenBucket(capacity, fillRate int, bucketLifetime time.Duration) *TokenBucket {
  18. return &TokenBucket{
  19. capacity: capacity,
  20. tokens: capacity,
  21. fillRate: fillRate,
  22. lastTimestamp: time.Now(),
  23. expirationTime: time.Now().Add(bucketLifetime),
  24. }
  25. }
  26. // TakeToken tries to retrieve a token from the bucket. Returns true if successful, false otherwise.
  27. // AddTokensToBucket adds tokens to the bucket based on the elapsed time and fill rate.
  28. func (tb *TokenBucket) AddTokensToBucket() {
  29. tb.mu.Lock()
  30. defer tb.mu.Unlock()
  31. currentTime := time.Now()
  32. elapsed := currentTime.Sub(tb.lastTimestamp).Milliseconds()
  33. fillAmount := int(elapsed) * tb.fillRate / 1000
  34. tb.tokens = tb.tokens + fillAmount
  35. if tb.tokens > tb.capacity {
  36. tb.tokens = tb.capacity
  37. }
  38. tb.lastTimestamp = time.Now()
  39. }
  40. // TakeToken tries to retrieve a token from the bucket. Returns true if successful, false otherwise.
  41. func (tb *TokenBucket) TakeToken() bool {
  42. tb.AddTokensToBucket()
  43. tb.mu.Lock()
  44. defer tb.mu.Unlock()
  45. if tb.tokens > 0 {
  46. tb.tokens--
  47. return true
  48. }
  49. return false
  50. }