rate.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package limiter
  2. import (
  3. "git.bvbej.com/bvbej/base-golang/pkg/ticker"
  4. "golang.org/x/time/rate"
  5. "sync"
  6. "time"
  7. )
  8. var _ RateLimiter = (*rateLimiter)(nil)
  9. type item struct {
  10. lastTime time.Time
  11. limiter *rate.Limiter
  12. }
  13. type RateLimiter interface {
  14. set(key string) *rate.Limiter
  15. get(key string) *rate.Limiter
  16. Allow(key string) bool
  17. }
  18. type rateLimiter struct {
  19. limit rate.Limit
  20. burst int
  21. list *sync.Map
  22. recycle ticker.Ticker
  23. }
  24. func NewRateLimiter(limit rate.Limit, burst int) RateLimiter {
  25. list := new(sync.Map)
  26. t := ticker.New(time.Minute)
  27. t.Process(func() {
  28. list.Range(func(key, value any) bool {
  29. if value.(*item).lastTime.Before(time.Now().Add(-time.Hour)) {
  30. list.Delete(key)
  31. }
  32. return true
  33. })
  34. })
  35. return &rateLimiter{
  36. list: list,
  37. limit: limit,
  38. recycle: t,
  39. burst: burst,
  40. }
  41. }
  42. func (i *rateLimiter) set(key string) *rate.Limiter {
  43. store := &item{
  44. lastTime: time.Now(),
  45. limiter: rate.NewLimiter(i.limit, i.burst),
  46. }
  47. i.list.Store(key, store)
  48. return store.limiter
  49. }
  50. func (i *rateLimiter) get(key string) *rate.Limiter {
  51. value, ok := i.list.Load(key)
  52. if !ok {
  53. return i.set(key)
  54. }
  55. value.(*item).lastTime = time.Now()
  56. i.list.Store(key, value)
  57. return value.(*item).limiter
  58. }
  59. func (i *rateLimiter) Allow(key string) bool {
  60. limiter := i.get(key)
  61. return limiter.Allow()
  62. }