Permalink
Browse files

added max requests feature

  • Loading branch information...
tstachl committed Feb 11, 2013
1 parent 534f27a commit 65da365475151526dac1a39cb582a5766eca4ebb
Showing with 141 additions and 13 deletions.
  1. +19 −13 lib/desk.rb
  2. +10 −0 lib/desk/configuration.rb
  3. +3 −0 lib/desk/error.rb
  4. +15 −0 lib/desk/request.rb
  5. +2 −0 spec/desk/api_spec.rb
  6. +92 −0 spec/desk_spec.rb
View
@@ -6,21 +6,27 @@
module Desk
extend Configuration
+ @counter = 0
+ @minute = Time.now.min
- # Alias for Desk::Client.new
- #
- # @return [Desk::Client]
- def self.client(options={})
- Desk::Client.new(options)
- end
+ class << self
+ attr_accessor :counter, :minute
+
+ # Alias for Desk::Client.new
+ #
+ # @return [Desk::Client]
+ def client(options={})
+ Desk::Client.new(options)
+ end
- # Delegate to Desk::Client
- def self.method_missing(method, *args, &block)
- return super unless client.respond_to?(method)
- client.send(method, *args, &block)
- end
+ # Delegate to Desk::Client
+ def method_missing(method, *args, &block)
+ return super unless client.respond_to?(method)
+ client.send(method, *args, &block)
+ end
- def self.respond_to?(method)
- client.respond_to?(method) || super
+ def respond_to?(method)
+ client.respond_to?(method) || super
+ end
end
end
View
@@ -10,11 +10,13 @@ module Configuration
:consumer_key,
:consumer_secret,
:format,
+ :max_requests,
:oauth_token,
:oauth_token_secret,
:proxy,
:subdomain,
:support_email,
+ :use_max_requests,
:user_agent,
:version].freeze
@@ -39,6 +41,12 @@ module Configuration
#
# @note JSON is preferred over XML because it is more concise and faster to parse.
DEFAULT_FORMAT = :json
+
+ # By default, set the max requests to 60 per minute
+ DEFAULT_MAX_REQUESTS = 60
+
+ # By default, don't use the max request feature
+ DEFAULT_USE_MAX_REQUESTS = false
# By default, don't set a user oauth token
DEFAULT_OAUTH_TOKEN = nil
@@ -85,11 +93,13 @@ def reset
self.consumer_key = DEFAULT_CONSUMER_KEY
self.consumer_secret = DEFAULT_CONSUMER_SECRET
self.format = DEFAULT_FORMAT
+ self.max_requests = DEFAULT_MAX_REQUESTS
self.oauth_token = DEFAULT_OAUTH_TOKEN
self.oauth_token_secret = DEFAULT_OAUTH_TOKEN_SECRET
self.proxy = DEFAULT_PROXY
self.subdomain = DEFAULT_SUBDOMAIN
self.support_email = DEFAULT_SUPPORT_EMAIL
+ self.use_max_requests = DEFAULT_USE_MAX_REQUESTS
self.user_agent = DEFAULT_USER_AGENT
self.version = DEFAULT_VERSION
self
View
@@ -50,6 +50,9 @@ def retry_after
@http_headers.values_at('retry-after', 'Retry-After').detect {|value| value }.to_i
end
end
+
+ # Raised when Desk max_requests is reached and use_max_requests is set to true
+ class TooManyRequests < StandardError; end
# Raised when Desk returns the HTTP status code 500
class InternalServerError < Error; end
View
@@ -22,9 +22,24 @@ def delete(path, options={}, raw=false)
end
private
+
+ def before_request
+ if Desk.minute != Time.now.min
+ Desk.minute = Time.now.min
+ Desk.counter = 0
+ end
+
+ Desk.counter += 1
+ if Desk.use_max_requests
+ if Desk.counter > Desk.max_requests
+ raise Desk::TooManyRequests
+ end
+ end
+ end
# Perform an HTTP request
def request(method, path, options, raw=false)
+ before_request
response = connection(raw).send(method) do |request|
case method
when :get, :delete
View
@@ -36,9 +36,11 @@
:oauth_token_secret => 'OS',
:adapter => :typhoeus,
:format => :xml,
+ :max_requests => 50,
:proxy => 'http://erik:sekret@proxy.example.com:8080',
:subdomain => 'zencoder',
:support_email => 'help@zencoder.com',
+ :use_max_requests => true,
:user_agent => 'Custom User Agent',
:version => "amazing"
}
View
@@ -98,6 +98,32 @@
Desk.format.should == 'xml'
end
end
+
+ describe ".max_requests" do
+ it "should return the default max requests" do
+ Desk.max_requests.should == Desk::Configuration::DEFAULT_MAX_REQUESTS
+ end
+ end
+
+ describe ".max_requests=" do
+ it "should set the max_requests" do
+ Desk.max_requests = 50
+ Desk.max_requests.should == 50
+ end
+ end
+
+ describe ".use_max_requests" do
+ it "should return the default max requests flag" do
+ Desk.use_max_requests.should == Desk::Configuration::DEFAULT_USE_MAX_REQUESTS
+ end
+ end
+
+ describe ".use_max_requests=" do
+ it "should set the use_max_requests flag" do
+ Desk.max_requests = true
+ Desk.max_requests.should == true
+ end
+ end
describe ".user_agent" do
it "should return the default user agent" do
@@ -124,4 +150,70 @@
end
end
end
+
+ describe ".counter" do
+ before do
+ Desk.counter = 0
+ stub_get("cases.json").
+ to_return(:body => fixture("cases.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ end
+
+ it "should be 0 in the beginning" do
+ Desk.counter.should == 0
+ end
+
+ it "should count the requests" do
+ 5.times {
+ Desk.cases
+ }
+ Desk.counter.should == 5
+ end
+
+ context "max requests enabled" do
+ before do
+ Desk.use_max_requests = true
+ end
+
+ it "should only allow 60 requests" do
+ expect {
+ 70.times {
+ Desk.cases
+ }
+ }.to raise_error
+ end
+
+ it "should only allow defined requests" do
+ Desk.max_requests = 50
+ expect {
+ 55.times {
+ Desk.cases
+ }
+ }.to raise_error
+ end
+
+ def make_request
+ Desk.cases
+ rescue Desk::TooManyRequests
+ sleep(5)
+ make_request
+ end
+
+ xit "should allow more requests after minute has passed" do
+ 70.times {
+ make_request
+ }
+ Desk.counter.should == 10
+ end
+ end
+ end
+
+ describe ".minute" do
+ before do
+ Desk.minute = Time.now.min
+ end
+
+ it "should be the current minute" do
+ Desk.minute.should == Time.now.min
+ end
+ end
end

0 comments on commit 65da365

Please sign in to comment.