mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-03-27 09:07:44 -04:00
Merge a2763d25b9 into 74059a1442
This commit is contained in:
commit
fdd5e343d4
1 changed files with 10 additions and 19 deletions
|
|
@ -26,11 +26,9 @@ module Vmpooler
|
||||||
client_id = identify_client(request)
|
client_id = identify_client(request)
|
||||||
endpoint_type = classify_endpoint(request)
|
endpoint_type = classify_endpoint(request)
|
||||||
|
|
||||||
# Check rate limits
|
# Atomically increment and check in one step
|
||||||
return rate_limit_response(client_id, endpoint_type) if rate_limit_exceeded?(client_id, endpoint_type, request)
|
current_count = increment_request_count(client_id, endpoint_type)
|
||||||
|
return rate_limit_response(client_id, endpoint_type) if current_count.nil? || current_count > limit_for(endpoint_type)
|
||||||
# Track the request
|
|
||||||
increment_request_count(client_id, endpoint_type)
|
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
@ -58,29 +56,22 @@ module Vmpooler
|
||||||
:global_per_ip
|
:global_per_ip
|
||||||
end
|
end
|
||||||
|
|
||||||
def rate_limit_exceeded?(client_id, endpoint_type, _request)
|
def limit_for(endpoint_type)
|
||||||
limit_config = @config[endpoint_type] || @config[:global_per_ip]
|
(@config[endpoint_type] || @config[:global_per_ip])[:limit]
|
||||||
key = "vmpooler__ratelimit__#{endpoint_type}__#{client_id}"
|
|
||||||
|
|
||||||
current_count = @redis.get(key).to_i
|
|
||||||
current_count >= limit_config[:limit]
|
|
||||||
rescue StandardError => e
|
|
||||||
# If Redis fails, allow the request through (fail open)
|
|
||||||
warn "Rate limiter Redis error: #{e.message}"
|
|
||||||
false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def increment_request_count(client_id, endpoint_type)
|
def increment_request_count(client_id, endpoint_type)
|
||||||
limit_config = @config[endpoint_type] || @config[:global_per_ip]
|
limit_config = @config[endpoint_type] || @config[:global_per_ip]
|
||||||
key = "vmpooler__ratelimit__#{endpoint_type}__#{client_id}"
|
key = "vmpooler__ratelimit__#{endpoint_type}__#{client_id}"
|
||||||
|
|
||||||
@redis.pipelined do |pipeline|
|
count = @redis.incr(key)
|
||||||
pipeline.incr(key)
|
# Only set expiry on first request in the window
|
||||||
pipeline.expire(key, limit_config[:period])
|
@redis.expire(key, limit_config[:period]) if count == 1
|
||||||
end
|
count
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
# Log error but don't fail the request
|
# Log error but don't fail the request
|
||||||
warn "Rate limiter increment error: #{e.message}"
|
warn "Rate limiter increment error: #{e.message}"
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def rate_limit_response(client_id, endpoint_type)
|
def rate_limit_response(client_id, endpoint_type)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue