Skip to content
Browse files

Throttle requests to 60 per minute.

  • Loading branch information...
1 parent 80993d6 commit b89cd8aa4beb9673788795df7ee43d362e03a4e2 @jyurek jyurek committed Mar 15, 2010
Showing with 72 additions and 0 deletions.
  1. +35 −0 lib/enforcer/repository.rb
  2. +37 −0 test/repository_test.rb
View
35 lib/enforcer/repository.rb
@@ -16,7 +16,41 @@ def initialize(account, api_key, project)
@api_key = api_key
end
+ def tick_api_counter!
+ now = Time.now
+ @@last_access ||= now
+ @@access_counter ||= 0
+ reset_counter if now - @@last_access > 60
+ @@access_counter += 1
+ end
+
+ def reset_counter
+ @@last_access = Time.now
+ @@access_counter = 0
+ end
+
+ def too_many_api_hits?
+ @@access_counter >= 60 && Time.now - @@last_access <= 60
+ end
+
+ def remaining_seconds
+ [60 - (Time.now - @@last_access), 0].max
+ end
+
+ def hit_count
+ @@access_counter
+ end
+
+ def throttle_to_the_minute!
+ tick_api_counter!
+ if too_many_api_hits?
+ puts "The GitHub API does not allow more than 60 requests per minute. Sleeping for #{remaining_seconds} seconds."
+ sleep( remaining_seconds )
+ end
+ end
+
def request(method, path)
+ throttle_to_the_minute!
begin
response = self.class.send(method, path, :body => { :login => @account, :token => @api_key })
response['collaborators']
@@ -40,6 +74,7 @@ def remove(collaborator)
end
def postreceive(hooks)
+ throttle_to_the_minute!
url = URI.parse "https://github.com/#{@account}/#{@project}/edit/postreceive_urls"
req = Net::HTTP::Post.new(url.path)
View
37 test/repository_test.rb
@@ -92,5 +92,42 @@ class RepositoryTest < Test::Unit::TestCase
assert_equal ["qrush"], @result
end
end
+
+ context "calling the API a lot in one minute" do
+ setup do
+ now = Time.now
+ stub(Time).now { now }
+ @repo.reset_counter
+ end
+
+ teardown do
+ @repo.reset_counter
+ end
+
+ should "keep track in the api counter" do
+ 65.times{ @repo.tick_api_counter! }
+ assert_equal 65, @repo.hit_count
+ assert @repo.too_many_api_hits?
+ end
+
+ should "make sure the time remaining is correct if we go over" do
+ 65.times{ @repo.tick_api_counter! }
+
+ now = Time.now + 10
+ stub(Time).now { now }
+
+ assert @repo.too_many_api_hits?
+ assert_equal 50, @repo.remaining_seconds
+ end
+
+ should "reset after a minute passes" do
+ 65.times{ @repo.tick_api_counter! }
+ now = Time.now + 61
+ stub(Time).now { now }
+ @repo.tick_api_counter!
+ assert_equal 1, @repo.hit_count
+ assert ! @repo.too_many_api_hits?
+ end
+ end
end
end

0 comments on commit b89cd8a

Please sign in to comment.
Something went wrong with that request. Please try again.