From 7e66f32ee57f0ae93e16bf2671b41f2c51c76183 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 17:23:02 +0100 Subject: [PATCH] ax(mining): rename rl receiver to limiter in RateLimiter methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AX Principle 1 — predictable names over short names. `rl` requires mental decoding; `limiter` is self-documenting at the call site. Co-Authored-By: Charon --- pkg/mining/ratelimiter.go | 80 +++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/pkg/mining/ratelimiter.go b/pkg/mining/ratelimiter.go index c4f13e1..08e22cc 100644 --- a/pkg/mining/ratelimiter.go +++ b/pkg/mining/ratelimiter.go @@ -8,8 +8,8 @@ import ( "github.com/gin-gonic/gin" ) -// rl := NewRateLimiter(10, 20) // 10 req/s, burst 20 -// router.Use(rl.Middleware()) +// limiter := NewRateLimiter(10, 20) // 10 req/s, burst 20 +// router.Use(limiter.Middleware()) type RateLimiter struct { requestsPerSecond int burst int @@ -24,10 +24,10 @@ type rateLimitClient struct { lastCheck time.Time } -// rl := NewRateLimiter(10, 20) // 10 requests/second, burst of 20 -// defer rl.Stop() +// limiter := NewRateLimiter(10, 20) // 10 requests/second, burst of 20 +// defer limiter.Stop() func NewRateLimiter(requestsPerSecond, burst int) *RateLimiter { - rl := &RateLimiter{ + limiter := &RateLimiter{ requestsPerSecond: requestsPerSecond, burst: burst, clients: make(map[string]*rateLimitClient), @@ -35,72 +35,72 @@ func NewRateLimiter(requestsPerSecond, burst int) *RateLimiter { } // Start cleanup goroutine - go rl.cleanupLoop() + go limiter.cleanupLoop() - return rl + return limiter } -// go rl.cleanupLoop() // started by NewRateLimiter; runs until rl.Stop() -func (rl *RateLimiter) cleanupLoop() { +// go limiter.cleanupLoop() // started by NewRateLimiter; runs until limiter.Stop() +func (limiter *RateLimiter) cleanupLoop() { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { select { - case <-rl.stopChan: + case <-limiter.stopChan: return case <-ticker.C: - rl.cleanup() + limiter.cleanup() } } } -// rl.cleanup() // called every minute by cleanupLoop; evicts IPs idle for >5 minutes -func (rl *RateLimiter) cleanup() { - rl.mutex.Lock() - defer rl.mutex.Unlock() +// limiter.cleanup() // called every minute by cleanupLoop; evicts IPs idle for >5 minutes +func (limiter *RateLimiter) cleanup() { + limiter.mutex.Lock() + defer limiter.mutex.Unlock() - for ip, client := range rl.clients { + for ip, client := range limiter.clients { if time.Since(client.lastCheck) > 5*time.Minute { - delete(rl.clients, ip) + delete(limiter.clients, ip) } } } -// rl.Stop() // call on shutdown to release the cleanup goroutine -func (rl *RateLimiter) Stop() { - rl.mutex.Lock() - defer rl.mutex.Unlock() +// limiter.Stop() // call on shutdown to release the cleanup goroutine +func (limiter *RateLimiter) Stop() { + limiter.mutex.Lock() + defer limiter.mutex.Unlock() - if !rl.stopped { - close(rl.stopChan) - rl.stopped = true + if !limiter.stopped { + close(limiter.stopChan) + limiter.stopped = true } } -// router.Use(rl.Middleware()) // install before route handlers -func (rl *RateLimiter) Middleware() gin.HandlerFunc { +// router.Use(limiter.Middleware()) // install before route handlers +func (limiter *RateLimiter) Middleware() gin.HandlerFunc { return func(c *gin.Context) { ip := c.ClientIP() - rl.mutex.Lock() - client, exists := rl.clients[ip] + limiter.mutex.Lock() + client, exists := limiter.clients[ip] if !exists { - client = &rateLimitClient{tokens: float64(rl.burst), lastCheck: time.Now()} - rl.clients[ip] = client + client = &rateLimitClient{tokens: float64(limiter.burst), lastCheck: time.Now()} + limiter.clients[ip] = client } // Token bucket algorithm now := time.Now() elapsed := now.Sub(client.lastCheck).Seconds() - client.tokens += elapsed * float64(rl.requestsPerSecond) - if client.tokens > float64(rl.burst) { - client.tokens = float64(rl.burst) + client.tokens += elapsed * float64(limiter.requestsPerSecond) + if client.tokens > float64(limiter.burst) { + client.tokens = float64(limiter.burst) } client.lastCheck = now if client.tokens < 1 { - rl.mutex.Unlock() + limiter.mutex.Unlock() respondWithError(c, http.StatusTooManyRequests, "RATE_LIMITED", "too many requests", "rate limit exceeded") c.Abort() @@ -108,14 +108,14 @@ func (rl *RateLimiter) Middleware() gin.HandlerFunc { } client.tokens-- - rl.mutex.Unlock() + limiter.mutex.Unlock() c.Next() } } -// if rl.ClientCount() == 0 { /* no active clients */ } -func (rl *RateLimiter) ClientCount() int { - rl.mutex.RLock() - defer rl.mutex.RUnlock() - return len(rl.clients) +// if limiter.ClientCount() == 0 { /* no active clients */ } +func (limiter *RateLimiter) ClientCount() int { + limiter.mutex.RLock() + defer limiter.mutex.RUnlock() + return len(limiter.clients) }