Class: Prop::Limiter

Inherits:
Object
  • Object
show all
Defined in:
lib/prop/limiter.rb

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.before_throttle_callbackObject

Returns the value of attribute before_throttle_callback.



9
10
11
# File 'lib/prop/limiter.rb', line 9

def before_throttle_callback
  @before_throttle_callback
end

.handlesObject

Returns the value of attribute handles.



9
10
11
# File 'lib/prop/limiter.rb', line 9

def handles
  @handles
end

.readerObject

Returns the value of attribute reader.



9
10
11
# File 'lib/prop/limiter.rb', line 9

def reader
  @reader
end

.writerObject

Returns the value of attribute writer.



9
10
11
# File 'lib/prop/limiter.rb', line 9

def writer
  @writer
end

Class Method Details

.before_throttle(&blk) ⇒ Object



19
20
21
# File 'lib/prop/limiter.rb', line 19

def before_throttle(&blk)
  self.before_throttle_callback = blk
end

.configure(handle, defaults) ⇒ Object

Public: Registers a handle for rate limiting

handle - the name of the handle you wish to use in your code, e.g. :login_attempt defaults - the settings for this handle, e.g. { :threshold => 5, :interval => 5.minutes }

Raises Prop::RateLimited if the number if the threshold for this handle has been reached

Raises:

  • (RuntimeError)


29
30
31
32
33
34
35
# File 'lib/prop/limiter.rb', line 29

def configure(handle, defaults)
  raise RuntimeError.new("Invalid threshold setting") unless defaults[:threshold].to_i > 0
  raise RuntimeError.new("Invalid interval setting")  unless defaults[:interval].to_i > 0

  self.handles ||= {}
  self.handles[handle] = defaults
end

.count(handle, key = nil, options = {}) ⇒ Object Also known as: query

Public: Counts the number of times the given handle/key combination has been hit in the current window

handle - the throttle identifier key - the associated key

Returns a count of hits in the current window



124
125
126
127
# File 'lib/prop/limiter.rb', line 124

def count(handle, key = nil, options = {})
  options, cache_key = prepare(handle, key, options)
  reader.call(cache_key).to_i
end

.disabled(&block) ⇒ Object

Public: Disables Prop for a block of code

block - a block of code within which Prop will not raise



40
41
42
43
44
45
# File 'lib/prop/limiter.rb', line 40

def disabled(&block)
  @disabled = true
  yield
ensure
  @disabled = false
end

.read(&blk) ⇒ Object



11
12
13
# File 'lib/prop/limiter.rb', line 11

def read(&blk)
  self.reader = blk
end

.reset(handle, key = nil, options = {}) ⇒ Object

Public: Resets a specific throttle

handle - the throttle identifier key - the associated key

Returns nothing



113
114
115
116
# File 'lib/prop/limiter.rb', line 113

def reset(handle, key = nil, options = {})
  options, cache_key = prepare(handle, key, options)
  writer.call(cache_key, 0)
end

.throttle(handle, key = nil, options = {}) ⇒ Object

Public: Records a single action for the given handle/key combination.

handle - the registered handle associated with the action key - a custom request specific key, e.g. [ account.id, “download”, request.remote_ip ] options - request specific overrides to the defaults configured for this handle (optional) a block of code that this throttle is guarding

Returns true if the threshold for this handle has been reached, else returns false



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/prop/limiter.rb', line 55

def throttle(handle, key = nil, options = {})
  options, cache_key = prepare(handle, key, options)
  counter = reader.call(cache_key).to_i

  unless disabled?
    if at_threshold?(counter, options[:threshold])
      unless before_throttle_callback.nil?
        before_throttle_callback.call(handle, key, options[:threshold], options[:interval])
      end

      true
    else
      increment = options.key?(:increment) ? options[:increment].to_i : 1
      writer.call(cache_key, counter + increment)

      yield if block_given?

      false
    end
  end
end

.throttle!(handle, key = nil, options = {}) ⇒ Object

Public: Records a single action for the given handle/key combination.

handle - the registered handle associated with the action key - a custom request specific key, e.g. [ account.id, “download”, request.remote_ip ] options - request specific overrides to the defaults configured for this handle (optional) a block of code that this throttle is guarding

Raises Prop::RateLimited if the number if the threshold for this handle has been reached Returns the value of the block if given a such, otherwise the current count of the throttle



86
87
88
89
90
91
92
93
94
# File 'lib/prop/limiter.rb', line 86

def throttle!(handle, key = nil, options = {})
  options, cache_key = prepare(handle, key, options)

  if throttle(handle, key, options)
    raise Prop::RateLimited.new(options.merge(:cache_key => cache_key, :handle => handle))
  end

  block_given? ? yield : reader.call(cache_key).to_i
end

.throttled?(handle, key = nil, options = {}) ⇒ Boolean

Public: Allows to query whether the given handle/key combination is currently throttled

handle - the throttle identifier key - the associated key

Returns true if a call to ‘throttle!` with same parameters would raise, otherwise false

Returns:

  • (Boolean)


102
103
104
105
# File 'lib/prop/limiter.rb', line 102

def throttled?(handle, key = nil, options = {})
  options, cache_key = prepare(handle, key, options)
  reader.call(cache_key).to_i >= options[:threshold]
end

.write(&blk) ⇒ Object



15
16
17
# File 'lib/prop/limiter.rb', line 15

def write(&blk)
  self.writer = blk
end