rate.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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, _ := i.list.LoadOrStore(key, &item{
  44. lastTime: time.Now(),
  45. limiter: rate.NewLimiter(i.limit, i.burst),
  46. })
  47. return store.(*item).limiter
  48. }
  49. func (i *rateLimiter) get(key string) *rate.Limiter {
  50. value, ok := i.list.Load(key)
  51. if !ok {
  52. return i.set(key)
  53. }
  54. value.(*item).lastTime = time.Now()
  55. i.list.Store(key, value)
  56. return value.(*item).limiter
  57. }
  58. func (i *rateLimiter) Allow(key string) bool {
  59. limiter := i.get(key)
  60. return limiter.Allow()
  61. }