Class: Sidekiq::Throttler::RateLimit

Inherits:
Object
  • Object
show all
Defined in:
lib/sidekiq/throttler/rate_limit.rb

Overview

Handles the tracking of rate limits.

TODO: Consider reducing threshold and period to smooth out job executions so that "24 jobs every 1 hour" becomes "1 job every 2 minutes and 30 seconds"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(worker, payload, queue, options = {}) ⇒ RateLimit

Returns a new instance of RateLimit


38
39
40
41
42
43
44
45
46
47
# File 'lib/sidekiq/throttler/rate_limit.rb', line 38

def initialize(worker, payload, queue, options = {})
  @worker = worker
  @payload = payload
  @queue = queue

  unless @storage_class = lookup_storage(options.fetch(:storage, :memory))
    raise ArgumentError,
      "Unrecognized storage backend: #{options[:storage].inspect}"
  end
end

Instance Attribute Details

#payloadArray (readonly)


19
20
21
# File 'lib/sidekiq/throttler/rate_limit.rb', line 19

def payload
  @payload
end

#queueString (readonly)


24
25
26
# File 'lib/sidekiq/throttler/rate_limit.rb', line 24

def queue
  @queue
end

#workerSidekiq::Worker (readonly)


14
15
16
# File 'lib/sidekiq/throttler/rate_limit.rb', line 14

def worker
  @worker
end

Instance Method Details

#can_throttle?true, false

Check if rate limiting options were correctly specified on the worker.


104
105
106
# File 'lib/sidekiq/throttler/rate_limit.rb', line 104

def can_throttle?
  [threshold, period].select(&:zero?).empty?
end

#countInteger

Fetch the number of jobs executed.


54
55
56
# File 'lib/sidekiq/throttler/rate_limit.rb', line 54

def count
  self.class.count(self)
end

#exceeded {|delay| ... } ⇒ Object

Set a callback to be executed when #execute is called and the rate limit has exceeded the threshold.

Yield Parameters:

  • delay (Integer)

    Delay in seconds to requeue job for.


137
138
139
# File 'lib/sidekiq/throttler/rate_limit.rb', line 137

def exceeded(&block)
  @exceeded = block
end

#exceeded?true, false

Check if rate limit has exceeded the threshold.


112
113
114
# File 'lib/sidekiq/throttler/rate_limit.rb', line 112

def exceeded?
  count >= threshold
end

#executeObject

Executes a callback (#within_bounds, or #exceeded) depending on the state of the rate limit.


144
145
146
147
148
149
150
151
152
153
# File 'lib/sidekiq/throttler/rate_limit.rb', line 144

def execute
  return @within_bounds.call unless can_throttle?

  if exceeded?
    @exceeded.call(period)
  else
    increment
    @within_bounds.call
  end
end

#executionsObject

Get the storage backend.


163
164
165
# File 'lib/sidekiq/throttler/rate_limit.rb', line 163

def executions
  @storage_class.instance
end

#incrementInteger

Increment the count of jobs executed.


63
64
65
# File 'lib/sidekiq/throttler/rate_limit.rb', line 63

def increment
  self.class.increment(self)
end

#keyString


92
93
94
95
96
97
98
# File 'lib/sidekiq/throttler/rate_limit.rb', line 92

def key
  @key ||= if options['key']
    options['key'].respond_to?(:call) ? options['key'].call(*payload) : options['key']
  else
    "#{@worker.class.to_s.underscore.gsub('/', ':')}:#{@queue}"
  end
end

#options{String => Float, Integer}

Returns the rate limit options for the current running worker.


71
72
73
# File 'lib/sidekiq/throttler/rate_limit.rb', line 71

def options
  @options ||= (worker.class.get_sidekiq_options['throttle'] || {}).stringify_keys
end

#periodFloat


85
86
87
# File 'lib/sidekiq/throttler/rate_limit.rb', line 85

def period
  @period ||= (options['period'].respond_to?(:call) ? options['period'].call(*payload) : options['period']).to_f
end

#reset!Object

Reset the tracking of job executions.


157
158
159
# File 'lib/sidekiq/throttler/rate_limit.rb', line 157

def reset!
  executions.reset
end

#thresholdInteger


78
79
80
# File 'lib/sidekiq/throttler/rate_limit.rb', line 78

def threshold
  @threshold ||= (options['threshold'].respond_to?(:call) ? options['threshold'].call(*payload) : options['threshold']).to_i
end

#within_bounds(&block) ⇒ Object

Set a callback to be executed when #execute is called and the rate limit has not exceeded the threshold.


127
128
129
# File 'lib/sidekiq/throttler/rate_limit.rb', line 127

def within_bounds(&block)
  @within_bounds = block
end

#within_bounds?true, false

Check if rate limit is within the threshold.


120
121
122
# File 'lib/sidekiq/throttler/rate_limit.rb', line 120

def within_bounds?
  !exceeded?
end