Skip to content

feat: per-IP rate limiting + TTL eviction for RateLimiter#14

Merged
pythondatascrape merged 1 commit into
mainfrom
feat/per-ip-ratelimit
May 6, 2026
Merged

feat: per-IP rate limiting + TTL eviction for RateLimiter#14
pythondatascrape merged 1 commit into
mainfrom
feat/per-ip-ratelimit

Conversation

@pythondatascrape
Copy link
Copy Markdown
Owner

Summary

  • Adds AllowIP(ip string) bool method with a separate namespace from per-client limiting
  • Adds NewRateLimiterWithTTL constructor and EvictStale() for idle-entry cleanup
  • Adds LimiterCount / IPLimiterCount accessors for test introspection

Test plan

  • TestAllowIP_* tests verify per-IP allow/block behaviour
  • TestEvictStale_IP confirms IP entries are evicted after TTL
  • All existing rate-limiter tests still pass

Closes #9, #6

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 6, 2026 14:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends internal/security’s RateLimiter to support a separate per-IP limiting namespace and adds TTL-based eviction utilities to mitigate unbounded growth of stored limiter entries.

Changes:

  • Added AllowIP(ip string) bool to rate-limit by IP independently of the existing per-client key space.
  • Added NewRateLimiterWithTTL(..., ttl) plus EvictStale() to support removing idle limiter entries.
  • Added limiter entry-count accessors intended for test introspection.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
internal/security/ratelimit.go Adds per-IP limiter map, TTL tracking, manual eviction method, and count accessors.
internal/security/ratelimit_test.go Adds tests for AllowIP behavior and a TTL eviction test for IP entries.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 25 to +33
// NewRateLimiter creates a RateLimiter with the given requests-per-minute and burst size.
func NewRateLimiter(rpm, burst int) *RateLimiter {
return NewRateLimiterWithTTL(rpm, burst, 10*time.Minute)
}

// NewRateLimiterWithTTL creates a RateLimiter whose idle entries are evicted after ttl.
func NewRateLimiterWithTTL(rpm, burst int, ttl time.Duration) *RateLimiter {
return &RateLimiter{
limiters: make(map[string]*rate.Limiter),
rpm: rpm,
burst: burst,
limiters: make(map[string]*entry),
Comment on lines +97 to +109
// LimiterCount returns the number of tracked client entries (for testing).
func (rl *RateLimiter) LimiterCount() int {
rl.mu.Lock()
defer rl.mu.Unlock()
return len(rl.limiters)
}

// IPLimiterCount returns the number of tracked IP entries (for testing).
func (rl *RateLimiter) IPLimiterCount() int {
rl.mu.Lock()
defer rl.mu.Unlock()
return len(rl.ipLimiters)
}
time.Sleep(100 * time.Millisecond)
rl.EvictStale()
require.Equal(t, 0, rl.IPLimiterCount())
}
Closes #9, #6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@pythondatascrape pythondatascrape force-pushed the feat/per-ip-ratelimit branch from 6ce6795 to 424d77e Compare May 6, 2026 16:09
@pythondatascrape pythondatascrape merged commit b1402ba into main May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: per-IP rate limiting alongside per-token rate limiting

2 participants