Class: RateLimit::Limiter

Inherits:
Object
  • Object
show all
Defined in:
lib/ratelimit-ruby.rb

Instance Method Summary collapse

Constructor Details

#initialize(apikey:, on_error: :log_and_pass, logger: nil, debug: false, local: false, stats: nil) ⇒ Limiter

Returns a new instance of Limiter.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ratelimit-ruby.rb', line 13

def initialize(apikey:, on_error: :log_and_pass, logger: nil, debug: false, local: false, stats: nil)
  @logger = (logger || Logger.new($stdout)).tap do |log|
    log.progname = "RateLimit"
  end
  @stats = (stats || NoopStats.new)
  @on_error = on_error
  @conn = Faraday.new(:url => self.base_url(local)) do |faraday|
    faraday.request :json # form-encode POST params
    faraday.response :logger if debug
    faraday.options[:open_timeout] = 2
    faraday.options[:timeout] = 5
    faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
  end
  (username, pass) = apikey.split("|")
  @conn.basic_auth(username, pass)
end

Instance Method Details

#acquire(group, acquire_amount, allow_partial_response: false) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/ratelimit-ruby.rb', line 56

def acquire(group, acquire_amount, allow_partial_response: false)
  result = @conn.post '/api/v1/limitcheck', { acquireAmount: acquire_amount,
                                              groups: [group],
                                              allowPartialResponse: allow_partial_response }.to_json
  handle_failure(result) unless result.success?
  res =JSON.parse(result.body, object_class: OpenStruct)
  res.amount ||= 0
  @stats.increment("it.ratelim.limitcheck", tags: ["policy_group:#{res.policyGroup}", "pass:#{res.passed}"])
  res
rescue => e
  handle_error(e)
end

#acquire_or_wait(key:, acquire_amount:, max_wait_secs:, init_backoff: 0) ⇒ Object

Raises:



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/ratelimit-ruby.rb', line 69

def acquire_or_wait(key:, acquire_amount:, max_wait_secs:, init_backoff: 0)
  start = Time.now
  sleep = init_backoff
  while Time.now - start < max_wait_secs
    sleep(sleep)
    res = acquire(key, acquire_amount)
    if res.passed
      return res
    end
    sleep += rand * WAIT_INCR_MAX
  end
  raise RateLimit::WaitExceeded
end

#base_url(local) ⇒ Object



9
10
11
# File 'lib/ratelimit-ruby.rb', line 9

def base_url(local)
  local ? 'http://localhost:8080' : 'http://www.ratelim.it'
end

#create_limit(group, limit, policy, burst: nil) ⇒ Object

create only. does not overwrite if it already exists



42
43
44
# File 'lib/ratelimit-ruby.rb', line 42

def create_limit(group, limit, policy, burst: nil)
  upsert(LimitDefinition.new(group, limit, policy, false, burst || limit), :post)
end

#create_returnable_limit(group, total_tokens, seconds_to_refill_one_token) ⇒ Object



31
32
33
# File 'lib/ratelimit-ruby.rb', line 31

def create_returnable_limit(group, total_tokens, seconds_to_refill_one_token)
  upsert_returnable_limit(group, total_tokens, seconds_to_refill_one_token, method: :post)
end

#pass?(group) ⇒ Boolean

Returns:



51
52
53
54
# File 'lib/ratelimit-ruby.rb', line 51

def pass?(group)
  result = acquire(group, 1)
  return result.passed
end

#return(limit_result) ⇒ Object



84
85
86
87
88
89
90
91
# File 'lib/ratelimit-ruby.rb', line 84

def return(limit_result)
  result = @conn.post '/api/v1/limitreturn',
             { enforcedGroup: limit_result.enforcedGroup,
               amount: limit_result.amount }.to_json
  handle_failure(result) unless result.success?
rescue => e
  handle_error(e)
end

#upsert_limit(group, limit, policy, burst: nil) ⇒ Object

upsert. overwrite whatever is there



47
48
49
# File 'lib/ratelimit-ruby.rb', line 47

def upsert_limit(group, limit, policy, burst: nil)
  upsert(LimitDefinition.new(group, limit, policy, false, burst || limit), :put)
end

#upsert_returnable_limit(group, total_tokens, seconds_to_refill_one_token, method: :put) ⇒ Object



35
36
37
38
39
# File 'lib/ratelimit-ruby.rb', line 35

def upsert_returnable_limit(group, total_tokens, seconds_to_refill_one_token, method: :put)
  recharge_rate = (24*60*60)/seconds_to_refill_one_token
  recharge_policy = DAILY_ROLLING
  upsert(LimitDefinition.new(group, recharge_rate, recharge_policy, true, total_tokens), method)
end