Class: SimpleThrottle

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

Overview

Create a simple throttle that can be used to limit the number of request for a resouce per time period. These objects are thread safe.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, limit:, ttl:) ⇒ SimpleThrottle

Create a new throttle with the given name. The ttl argument specifies the time range that is being used for measuring in seconds while the limit specifies how many calls are allowed in that range.



47
48
49
50
51
52
53
# File 'lib/simple_throttle.rb', line 47

def initialize(name, limit:, ttl:)
  @name = name.to_s
  @name.freeze unless @name.frozen?
  @limit = limit
  @ttl = ttl
  @script_sha_1 = nil
end

Instance Attribute Details

#limitObject (readonly)

Returns the value of attribute limit.



42
43
44
# File 'lib/simple_throttle.rb', line 42

def limit
  @limit
end

#nameObject (readonly)

Returns the value of attribute name.



42
43
44
# File 'lib/simple_throttle.rb', line 42

def name
  @name
end

#ttlObject (readonly)

Returns the value of attribute ttl.



42
43
44
# File 'lib/simple_throttle.rb', line 42

def ttl
  @ttl
end

Class Method Details

.[](name) ⇒ Object

Returns a globally defined throttle with the specfied name.



15
16
17
18
19
20
21
# File 'lib/simple_throttle.rb', line 15

def [](name)
  if defined?(@throttles) && @throttles
    @throttles[name.to_s]
  else
    nil
  end
end

.add(name, limit:, ttl:) ⇒ Object

Add a new throttle that can be referenced later with the [] method.



9
10
11
12
# File 'lib/simple_throttle.rb', line 9

def add(name, limit:, ttl:)
  @throttles ||= {} 
  @throttles[name.to_s] = new(name, limit: limit, ttl: ttl)       
end

.redisObject

Return the Redis instance where the throttles are stored.



33
34
35
36
37
38
39
# File 'lib/simple_throttle.rb', line 33

def redis
  if @redis_client.is_a?(Proc)
    @redis_client.call
  else
    @redis_client
  end
end

.set_redis(client = nil, &block) ⇒ Object

Set the Redis instance to use for maintaining the throttle. This can either be set with a hard coded value or by the value yielded by a block. If the block form is used it will be invoked at runtime to get the instance. Use this method if your Redis instance isn’t constant (for example if you’re in a forking environment and re-initialize connections on fork)



28
29
30
# File 'lib/simple_throttle.rb', line 28

def set_redis(client = nil, &block)
  @redis_client = (client || block)
end

Instance Method Details

#allowed!Object

Returns true if the limit for the throttle has not been reached yet. This method will also track the throttled resource as having been invoked on each call.



57
58
59
60
61
62
63
64
# File 'lib/simple_throttle.rb', line 57

def allowed!
  size = current_size(true)
  if size < limit
    true
  else
    false
  end
end

#peekObject

Peek at the current number for throttled calls being tracked.



72
73
74
# File 'lib/simple_throttle.rb', line 72

def peek
  current_size(false)
end

#reset!Object

Reset a throttle back to zero.



67
68
69
# File 'lib/simple_throttle.rb', line 67

def reset!
  self.class.redis.del(redis_key)
end

#wait_timeObject

Returns when the next resource call should be allowed. Note that this doesn’t guarantee that calling allow! will return true if the wait time is zero since other processes or threads can claim the resource.



79
80
81
82
83
84
85
86
87
88
# File 'lib/simple_throttle.rb', line 79

def wait_time
  if peek < limit
    0.0
  else
    first = self.class.redis.lindex(redis_key, 0).to_f / 1000.0
    delta = Time.now.to_f - first
    delta = 0.0 if delta < 0
    delta
  end
end