Skip to content

Instantly share code, notes, and snippets.

@sharshenov
Created April 19, 2016 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sharshenov/34f6a1ff5eebe414d7dd8b4ecbfc788c to your computer and use it in GitHub Desktop.
Save sharshenov/34f6a1ff5eebe414d7dd8b4ecbfc788c to your computer and use it in GitHub Desktop.
Basic throttler
class Throttler
class << self
def limit *attrs
throttler.limit *attrs
end
private
def throttler
@throttler ||= new
end
end
attr_reader :storage
def initialize storage=nil
@mutex = Mutex.new
@storage = storage || Hash.new
end
def limit seconds, key='default'
while not allowed?(seconds, key)
sleep 0.01
end
yield if block_given?
end
private
def allowed? seconds, key
@mutex.synchronize do
now = Time.now.to_f
timestamp = get(key)
if timestamp.nil? or timestamp < now - seconds
set(key, now)
true
else
false
end
end
end
def get key
value = storage[key]
if value and not value.is_a?(Float)
value.to_f
else
value
end
end
def set key, value
storage[key] = value
end
end
@sharshenov
Copy link
Author

Usage examples

Limit rate

Throttler.limit 1.minute do
  do_request_to_api
end

Limit rate with personal lock

threads = []

threads << Thread.new do
  Throttler.limit(10.seconds, "API_1") { do_request_to_api_1 }
end

threads << Thread.new do
  Throttler.limit(15.seconds, "API_2") { do_request_to_api_2 }
end

threads.each(&:join)

Use Redis as key-value storage

redis = Redis.new

throttler = Throttler.new redis

throttler.limit(1.minute) { do_request_to_api }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment