64 lines
1.1 KiB
Go
64 lines
1.1 KiB
Go
|
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
|
||
|
}
|