ceremonyclient/node/consensus/data/grpc_worker_rate_limiter.go
2024-11-11 13:30:04 -06:00

60 lines
1.0 KiB
Go

package data
import (
"sync"
"time"
"github.com/libp2p/go-libp2p/core/peer"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type RateLimiter struct {
mu sync.RWMutex
clients map[peer.ID]time.Time
maxTokens int
windowSize time.Duration
}
type bucket struct {
tokens int
lastSeen time.Time
}
func NewRateLimiter(
maxTokens int,
windowSize time.Duration,
) *RateLimiter {
return &RateLimiter{
clients: make(map[peer.ID]time.Time),
maxTokens: maxTokens,
windowSize: windowSize,
}
}
func (rl *RateLimiter) Allow(peerId peer.ID) error {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
windowStart := now.Add(-rl.windowSize)
for peerId, time := range rl.clients {
if time.Before(windowStart) {
delete(rl.clients, peerId)
}
}
if _, exists := rl.clients[peerId]; !exists {
if len(rl.clients) >= rl.maxTokens {
return status.Errorf(codes.ResourceExhausted,
"maximum number of unique callers (%d) reached", rl.maxTokens)
}
}
rl.clients[peerId] = now
return nil
}