class Sidekiq::Throttled::Strategy::Threshold
Threshold
throttling strategy @todo Use redis TIME command instead of sending current timestamp from
sidekiq manager. See: http://redis.io/commands/time
Constants
- SCRIPT
-
LUA script used to limit fetch threshold. Logic behind the scene can be described in following pseudo code:
def exceeded? limit <= LLEN(@key) && NOW - LINDEX(@key, -1) < @period end def increase! LPUSH(@key, NOW) LTRIM(@key, 0, @limit - 1) EXPIRE(@key, @period) end return 1 if exceeded? increase! return 0
Public Class Methods
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 41 def initialize(strategy_key, limit:, period:, key_suffix: nil) @base_key = "#{strategy_key}:threshold" @limit = limit @period = period @key_suffix = key_suffix end
@param [#to_s] strategy_key @param [#to_i, call] limit Amount of allowed concurrent jobs
per period running for given key.
@param [#to_f, call] :period Period in seconds. @param [Proc] key_suffix Dynamic key suffix generator.
Public Instance Methods
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 92 def count(*job_args) Sidekiq.redis { |conn| conn.llen(key(job_args)) }.to_i end
@return [Integer] Current count of jobs
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 56 def dynamic? @key_suffix || @limit.respond_to?(:call) || @period.respond_to?(:call) end
@return [Boolean] Whenever strategy has dynamic config
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 49 def period(job_args = nil) return @period.to_f unless @period.respond_to? :call @period.call(*job_args).to_f end
@return [Float] Period in seconds
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 98 def reset!(*job_args) Sidekiq.redis { |conn| conn.del(key(job_args)) } end
Resets count of jobs @return [void]
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 73 def retry_in(*job_args) job_limit = limit(job_args) return 0.0 if !job_limit || count(*job_args) < job_limit job_period = period(job_args) job_key = key(job_args) time_since_oldest = Time.now.to_f - Sidekiq.redis { |redis| redis.lindex(job_key, -1) }.to_f if time_since_oldest > job_period # The oldest job on our list is from more than the throttling period ago, # which means we have not hit the limit this period. 0.0 else # If we can only have X jobs every Y minutes, then wait until Y minutes have elapsed # since the oldest job on our list. job_period - time_since_oldest end end
@return [Float] How long, in seconds, before we’ll next be able to take on jobs
Source
# File lib/sidekiq/throttled/strategy/threshold.rb, line 61 def throttled?(*job_args) job_limit = limit(job_args) return false unless job_limit return true if job_limit <= 0 keys = [key(job_args)] argv = [job_limit, period(job_args), Time.now.to_f] Sidekiq.redis { |redis| 1 == SCRIPT.call(redis, keys: keys, argv: argv) } end
@return [Boolean] whenever job is throttled or not