-
-
Save kivanio/85679b1062d24bd7080e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExternalService | |
include RateLimiter | |
def self.work_with_users | |
rate_limit 20, 2.0, User.find_each do |user| | |
# Do stuff with each user. | |
# Pause 2 seconds every 20 iterations | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExternalService | |
def self.work_with_users | |
rate_limiter = 0 | |
User.find_each do |user| | |
# Do stuff with each user | |
rate_limiter += 1 | |
sleep 0.8 if rate_limiter % 10 == 0 | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module RateLimiter | |
extend ActiveSupport::Concern | |
def rate_limit *args, &block | |
self.class.rate_limit(*args, &block) | |
end | |
module ClassMethods | |
def rate_limit allowed_iterations, sleep_time, enum | |
enum.each_with_index do |data, runs| | |
yield data | |
sleep sleep_time if (runs+1) % allowed_iterations == 0 | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe RateLimiter do | |
let(:enum) { 1..10 } | |
subject { klass.new } | |
describe '.rate_limit' do | |
it 'accepts two parameters' do | |
expect(klass.method(:rate_limit).arity).to eql 3 | |
end | |
it 'yields to a block' do | |
expect do |var| | |
klass.rate_limit 1, 0.0, enum, &var | |
end.to yield_successive_args(*enum.to_a) | |
end | |
it 'sleeps every n iterations' do | |
limit = 3 | |
klass.stub(:sleep) | |
klass.should_receive(:sleep).exactly(enum.size / limit).times | |
klass.rate_limit limit, 10.0, enum, &Proc.new{} | |
end | |
end | |
describe '#rate_limit' do | |
it 'forwards do its singleton version' do | |
klass.should_receive(:rate_limit).with 10, 1.0, enum | |
subject.rate_limit 10, 1.0, enum, &Proc.new{} | |
end | |
it 'yields to a block' do | |
expect do |var| | |
subject.rate_limit 1, 0.0, enum, &var | |
end.to yield_successive_args(*enum.to_a) | |
end | |
end | |
def klass | |
@klass ||= Class.new { include RateLimiter } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment