class ExcessFlow::SlidingWindowStrategy

ExcessFlow::SlidingWindowStrategy

Definition of sliging window rate limiting strategy and it's behaviour implementations. Sliding window allows only N requests for a given key to be done in a trailing O time window where O start is defined as `now` - `window_size`. Window expiration starts with the first request for a given key. Once expired it will reset back to 0.

Public Instance Methods

within_rate_limit?() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 26
def within_rate_limit?
  ExcessFlow::GlobalMutex.locked(lock_key: configuration.lock_key) do
    cleanup_stale_counters

    if current_requests < configuration.limit
      bump_counter
      start_expiration_window

      true
    else
      false
    end
  end
end

Private Instance Methods

bump_counter() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 43
def bump_counter
  ExcessFlow.redis do |r|
    r.zadd(
      configuration.counter_key,
      current_timestamp,
      SecureRandom.uuid
    )
  end
end
cleanup_stale_counters() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 53
def cleanup_stale_counters
  ExcessFlow.redis do |r|
    r.zremrangebyscore(configuration.counter_key, 0, "(#{window_start}")
  end
end
current_requests() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 59
def current_requests
  @current_requests ||= ExcessFlow.redis { |r| r.zcount(configuration.counter_key, '-inf', '+inf') }
end
current_timestamp() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 67
def current_timestamp
  @current_timestamp ||= (Time.now.to_f * 100_000).to_i
end
current_ttl() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 63
def current_ttl
  @current_ttl ||= ExcessFlow.redis { |r| r.ttl(configuration.counter_key) }.to_i
end
start_expiration_window() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 71
def start_expiration_window
  return if current_ttl.negative?

  ExcessFlow.redis { |r| r.expire(configuration.counter_key, configuration.ttl) }
end
window_start() click to toggle source
# File lib/excess_flow/sliding_window_strategy.rb, line 77
def window_start
  @window_start ||= current_timestamp - (configuration.ttl * 100_000)
end