amocrm/pkg/amoClient/limiter.go

64 lines
1.1 KiB
Go
Raw Normal View History

2024-04-10 10:53:19 +00:00
package amoClient
import (
"context"
"sync"
"time"
)
type RateLimiter struct {
requests chan struct{}
done chan struct{}
maxRequests int
interval time.Duration
mutex sync.Mutex
cancel context.CancelFunc
}
func NewRateLimiter(ctx context.Context, maxRequests int, interval time.Duration) *RateLimiter {
limiter := &RateLimiter{
requests: make(chan struct{}, maxRequests),
done: make(chan struct{}),
maxRequests: maxRequests,
interval: interval,
}
ctx, cancel := context.WithCancel(ctx)
limiter.cancel = cancel
go limiter.start(ctx)
return limiter
}
func (limiter *RateLimiter) start(ctx context.Context) {
ticker := time.NewTicker(limiter.interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
limiter.mutex.Lock()
for i := 0; i < len(limiter.requests); i++ {
<-limiter.requests
}
limiter.mutex.Unlock()
case <-ctx.Done():
return
}
}
}
func (limiter *RateLimiter) Check() bool {
select {
case limiter.requests <- struct{}{}:
return true
default:
return false
}
}
func (limiter *RateLimiter) Stop(ctx context.Context) error {
limiter.cancel()
return nil
}