FIX: regression around rate limiter
This commit is contained in:
parent
dd70ef3abf
commit
5a9622163d
|
@ -7,7 +7,7 @@ class RateLimiter
|
||||||
attr_reader :max, :secs, :user, :key
|
attr_reader :max, :secs, :user, :key
|
||||||
|
|
||||||
def self.key_prefix
|
def self.key_prefix
|
||||||
"l-rate-limit:"
|
"l-rate-limit2:"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.disable
|
def self.disable
|
||||||
|
@ -76,7 +76,7 @@ class RateLimiter
|
||||||
|
|
||||||
def performed!
|
def performed!
|
||||||
return if rate_unlimited?
|
return if rate_unlimited?
|
||||||
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i
|
||||||
if eval_lua(PERFORM_LUA, PERFORM_LUA_SHA, [prefixed_key], [now, @secs, @max]) == 0
|
if eval_lua(PERFORM_LUA, PERFORM_LUA_SHA, [prefixed_key], [now, @secs, @max]) == 0
|
||||||
raise RateLimiter::LimitExceeded.new(seconds_to_wait, @type)
|
raise RateLimiter::LimitExceeded.new(seconds_to_wait, @type)
|
||||||
end
|
end
|
||||||
|
@ -97,7 +97,7 @@ class RateLimiter
|
||||||
return @max if @user && @user.staff?
|
return @max if @user && @user.staff?
|
||||||
|
|
||||||
arr = redis.lrange(prefixed_key, 0, @max) || []
|
arr = redis.lrange(prefixed_key, 0, @max) || []
|
||||||
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i
|
||||||
arr.reject! { |a| (t0 - a.to_i) > @secs }
|
arr.reject! { |a| (t0 - a.to_i) > @secs }
|
||||||
@max - arr.size
|
@max - arr.size
|
||||||
end
|
end
|
||||||
|
@ -122,7 +122,7 @@ class RateLimiter
|
||||||
|
|
||||||
def age_of_oldest
|
def age_of_oldest
|
||||||
# age of oldest event in buffer, in seconds
|
# age of oldest event in buffer, in seconds
|
||||||
Process.clock_gettime(Process::CLOCK_MONOTONIC) - redis.lrange(prefixed_key, -1, -1).first.to_i
|
Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i - redis.lrange(prefixed_key, -1, -1).first.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_under_limit?
|
def is_under_limit?
|
||||||
|
|
|
@ -2,7 +2,7 @@ class RateLimiter
|
||||||
|
|
||||||
# A rate limit has been exceeded.
|
# A rate limit has been exceeded.
|
||||||
class LimitExceeded < StandardError
|
class LimitExceeded < StandardError
|
||||||
attr_reader :type
|
attr_reader :type, :available_in
|
||||||
|
|
||||||
def initialize(available_in, type = nil)
|
def initialize(available_in, type = nil)
|
||||||
@available_in = available_in
|
@available_in = available_in
|
||||||
|
|
|
@ -39,12 +39,22 @@ describe RateLimiter do
|
||||||
context 'global rate limiter' do
|
context 'global rate limiter' do
|
||||||
|
|
||||||
it 'can operate in global mode' do
|
it 'can operate in global mode' do
|
||||||
limiter = RateLimiter.new(nil, "test", 2, 10, global: true)
|
limiter = RateLimiter.new(nil, "test", 2, 30, global: true)
|
||||||
limiter.clear!
|
limiter.clear!
|
||||||
|
|
||||||
|
thrown = false
|
||||||
|
|
||||||
limiter.performed!
|
limiter.performed!
|
||||||
limiter.performed!
|
limiter.performed!
|
||||||
expect { limiter.performed! }.to raise_error(RateLimiter::LimitExceeded)
|
begin
|
||||||
|
limiter.performed!
|
||||||
|
rescue RateLimiter::LimitExceeded => e
|
||||||
|
expect(e.available_in.class).to eq(Integer)
|
||||||
|
expect(e.available_in).to be > 28
|
||||||
|
expect(e.available_in).to be < 32
|
||||||
|
thrown = true
|
||||||
|
end
|
||||||
|
expect(thrown).to be(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue