dhc 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ca76978c02b0282cb78e1bdca008c209ea28f8a23f424fbb94c4aec639c4ccc
4
- data.tar.gz: 42cd56ebb4db087b70a3ade68b56ac7da0cb823b3b19751c2dda1accca4c7a86
3
+ metadata.gz: dbcbbfbe466771c1ad389aebe29d997915137216b50b0aceff73f3cbc589f050
4
+ data.tar.gz: a659a0b022d803a700352d20fe96482731470b31234e8db9df3f665da5547ae7
5
5
  SHA512:
6
- metadata.gz: a1d76646f40bf13cb1e773b6e851f1923a53457d3e4b51ba4f7bf88f2e9e2c923d71d99cd32846ec564c19eb94dc2933303a2aa61298a8f7010ba41dd939676a
7
- data.tar.gz: 472a083db1738e1e12e3a611e8c133add777d3b6adc67ebbae5f124dc5fb550452e4d10604233361d935b201f8d9598bdc23d40e799e1d8f4f785ff5469b0f0a
6
+ metadata.gz: 1851454238cb9552457a56c020edcb88b8b7e37eed6ebc0c6d1a8574c8250c520cfd48d8ca1e9f82ddcd334085daf1651fb0c31221ea638921aeb5873218846f
7
+ data.tar.gz: 4432965dcb69081d1d082cfc47101644a817f387d79213f57b8d2b80192901148e49b6a9ceb4ddb10c632e425385b30026de4c2bbbe69ffdaeefb5bf105c6bf5
data/.rubocop.yml CHANGED
@@ -62,6 +62,9 @@ Style/SingleArgumentDig:
62
62
  Metrics/ClassLength:
63
63
  Enabled: false
64
64
 
65
+ Metrics/PerceivedComplexity:
66
+ Enabled: false
67
+
65
68
  Style/OptionalBooleanParameter:
66
69
  Enabled: false
67
70
 
data/README.md CHANGED
@@ -854,6 +854,8 @@ If it raises, it forwards the request and response object to rollbar, which cont
854
854
 
855
855
  The throttle interceptor allows you to raise an exception if a predefined quota of a provider request limit is reached in advance.
856
856
 
857
+ The throttle state (tracker) is stored in Rails.cache.
858
+
857
859
  ```ruby
858
860
  DHC.configure do |c|
859
861
  c.interceptors = [DHC::Throttle]
@@ -889,10 +891,33 @@ DHC.get('http://depay.fi', options)
889
891
  * `remaining`:
890
892
  * a hash pointing at the response header containing the current amount of remaining requests
891
893
  * a proc that receives the response as argument and returns the current amount of remaining requests
894
+ * not set: will track remaining by counting down limit until `expires`
892
895
  * `expires`:
893
896
  * a hash pointing at the response header containing the timestamp when the quota will reset
894
897
  * a proc that receives the response as argument and returns the timestamp when the quota will reset
898
+ * an ActiveSupport::Duration e.g. 1.minute
899
+
900
+ Example for throttling manually without relating to any information in the response:
895
901
 
902
+ ```ruby
903
+ options = {
904
+ throttle: {
905
+ track: true,
906
+ break: '80%',
907
+ provider: 'depay.fi',
908
+ limit: 100,
909
+ expires: 1.minute
910
+ }
911
+ }
912
+
913
+ DHC.get('http://depay.fi', options)
914
+ ```
915
+
916
+ Will reset every minute, and will allow up to 80 requests per minute. The 81st request attempt within a minute will raise:
917
+
918
+ ```ruby
919
+ DHC::Throttle::OutOfQuota: Reached predefined quota for depay.fi
920
+ ```
896
921
 
897
922
  #### Zipkin
898
923
 
data/dhc.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
 
29
29
  s.add_development_dependency 'prometheus-client', '~> 0.7.1'
30
30
  s.add_development_dependency 'pry'
31
- s.add_development_dependency 'rails', '>= 5.2'
31
+ s.add_development_dependency 'rails', '>= 5.2', '< 7'
32
32
  s.add_development_dependency 'redis'
33
33
  s.add_development_dependency 'rspec-rails', '>= 3.0.0'
34
34
  s.add_development_dependency 'rubocop'
data/lib/dhc/error.rb CHANGED
@@ -70,10 +70,7 @@ class DHC::Error < StandardError
70
70
 
71
71
  debug = []
72
72
  debug << [request.method, request.url].map { |str| self.class.fix_invalid_encoding(str) }.join(' ')
73
- debug << "Options: #{request.options}"
74
- debug << "Headers: #{request.headers}"
75
73
  debug << "Response Code: #{response.code} (#{response.options[:return_code]})"
76
- debug << "Response Options: #{response.options}"
77
74
  debug << response.body
78
75
  debug << _message
79
76
 
@@ -23,12 +23,12 @@ class DHC::Caching < DHC::Interceptor
23
23
  def fetch(key)
24
24
  central_response = @central[:read].fetch(key) if @central && @central[:read].present?
25
25
  if central_response
26
- puts %([DHC] served from central cache: "#{key}")
26
+ DHC::Logger.info %([DHC] served from central cache: "#{key}")
27
27
  return central_response
28
28
  end
29
29
  local_response = @local.fetch(key) if @local
30
30
  if local_response
31
- puts %([DHC] served from local cache: "#{key}")
31
+ DHC::Logger.info %([DHC] served from local cache: "#{key}")
32
32
  return local_response
33
33
  end
34
34
  end
@@ -6,80 +6,117 @@ class DHC::Throttle < DHC::Interceptor
6
6
  class OutOfQuota < StandardError
7
7
  end
8
8
 
9
+ CACHE_KEY = 'DHC/throttle/tracker/v1'
10
+
9
11
  class << self
10
- attr_accessor :track
12
+
13
+ def tracker(provider)
14
+ (Rails.cache.read(CACHE_KEY) || {})[provider] || {}
15
+ end
16
+
17
+ def tracker=(track)
18
+ Rails.cache.write(CACHE_KEY, (Rails.cache.read(CACHE_KEY) || {}).merge({ track[:provider] => track }))
19
+ end
11
20
  end
12
21
 
13
22
  def before_request
14
- options = request.options.dig(:throttle)
15
23
  return unless options
16
- break_options = options.dig(:break)
17
- return unless break_options
18
- break_when_quota_reached! if break_options.match('%')
24
+ break! if break?
19
25
  end
20
26
 
21
27
  def after_response
22
- options = response.request.options.dig(:throttle)
23
- return unless throttle?(options)
24
- self.class.track ||= {}
25
- self.class.track[options.dig(:provider)] = {
26
- limit: limit(options: options[:limit], response: response),
27
- remaining: remaining(options: options[:remaining], response: response),
28
- expires: expires(options: options[:expires], response: response)
28
+ return unless track?
29
+ self.class.tracker = {
30
+ provider: options.dig(:provider),
31
+ limit: limit,
32
+ remaining: remaining,
33
+ expires: expires
29
34
  }
30
35
  end
31
36
 
32
37
  private
33
38
 
34
- def throttle?(options)
35
- [options&.dig(:track), response.headers].none?(&:blank?)
39
+ def options
40
+ @options ||= request.options.dig(:throttle) || {}
41
+ end
42
+
43
+ def provider
44
+ @provider ||= request.options.dig(:throttle, :provider)
45
+ end
46
+
47
+ def track?
48
+ (options.dig(:remaining) && [options.dig(:track), response.headers].none?(&:blank?) ||
49
+ options.dig(:track).present?
50
+ )
51
+ end
52
+
53
+ def break?
54
+ @do_break ||= begin
55
+ return if options.dig(:break) && !options.dig(:break).match('%')
56
+ tracker = self.class.tracker(options[:provider])
57
+ return if tracker.blank? || tracker[:remaining].blank? || tracker[:limit].blank? || tracker[:expires].blank?
58
+ return if Time.zone.now > tracker[:expires]
59
+ remaining = tracker[:remaining] * 100
60
+ limit = tracker[:limit]
61
+ remaining_quota = 100 - options[:break].to_i
62
+ remaining < remaining_quota * limit
63
+ end
36
64
  end
37
65
 
38
- def break_when_quota_reached!
39
- options = request.options.dig(:throttle)
40
- track = (self.class.track || {}).dig(options[:provider])
41
- return if track.blank? || track[:remaining].blank? || track[:limit].blank? || track[:expires].blank?
42
- return if Time.zone.now > track[:expires]
43
- # avoid floats by multiplying with 100
44
- remaining = track[:remaining] * 100
45
- limit = track[:limit]
46
- quota = 100 - options[:break].to_i
47
- raise(OutOfQuota, "Reached predefined quota for #{options[:provider]}") if remaining < quota * limit
66
+ def break!
67
+ raise(OutOfQuota, "Reached predefined quota for #{provider}")
48
68
  end
49
69
 
50
- def limit(options:, response:)
70
+ def limit
51
71
  @limit ||=
52
- if options.is_a?(Proc)
53
- options.call(response)
54
- elsif options.is_a?(Integer)
55
- options
56
- elsif options.is_a?(Hash) && options[:header]
57
- response.headers[options[:header]]&.to_i
72
+ if options.dig(:limit).is_a?(Proc)
73
+ options.dig(:limit).call(response)
74
+ elsif options.dig(:limit).is_a?(Integer)
75
+ options.dig(:limit)
76
+ elsif options.dig(:limit).is_a?(Hash) && options.dig(:limit, :header) && response.headers
77
+ response.headers[options.dig(:limit, :header)]&.to_i
58
78
  end
59
79
  end
60
80
 
61
- def remaining(options:, response:)
62
- @remaining ||=
63
- begin
64
- if options.is_a?(Proc)
65
- options.call(response)
66
- elsif options.is_a?(Hash) && options[:header]
67
- response.headers[options[:header]]&.to_i
81
+ def remaining
82
+ @remaining ||= begin
83
+ if options.dig(:remaining).is_a?(Proc)
84
+ options.dig(:remaining).call(response)
85
+ elsif options.dig(:remaining).is_a?(Hash) && options.dig(:remaining, :header) && response.headers
86
+ response.headers[options.dig(:remaining, :header)]&.to_i
87
+ elsif options.dig(:remaining).blank?
88
+ remaining_before = self.class.tracker(provider).dig(:remaining) || request.options.dig(:throttle, :limit)
89
+ expires = self.class.tracker(provider).dig(:expires)
90
+ if expires && expires > DateTime.now
91
+ remaining_before - 1
92
+ else
93
+ request.options.dig(:throttle, :limit) - 1
68
94
  end
69
95
  end
96
+ end
70
97
  end
71
98
 
72
- def expires(options:, response:)
73
- @expires ||= convert_expires(read_expire_option(options, response))
74
- end
99
+ def expires
100
+ @expires ||= begin
101
+ if options.dig(:expires).is_a?(ActiveSupport::Duration) && self.class.tracker(provider).dig(:expires).present?
102
+ if self.class.tracker(provider)[:expires] > DateTime.now
103
+ self.class.tracker(provider)[:expires]
104
+ else
105
+ DateTime.now + options.dig(:expires)
106
+ end
107
+ elsif options.dig(:expires).is_a?(Hash) && options.dig(:expires, :header)
75
108
 
76
- def read_expire_option(options, response)
77
- (options.is_a?(Hash) && options[:header]) ? response.headers[options[:header]] : options
109
+ convert_expire_value(response.headers[options.dig(:expires, :header)]) if response.headers
110
+ else
111
+ convert_expire_value(options.dig(:expires))
112
+ end
113
+ end
78
114
  end
79
115
 
80
- def convert_expires(value)
116
+ def convert_expire_value(value)
81
117
  return if value.blank?
82
118
  return value.call(response) if value.is_a?(Proc)
119
+ return DateTime.now + value if value.is_a?(ActiveSupport::Duration)
83
120
  return Time.parse(value) if value.match(/GMT/)
84
121
  Time.zone.at(value.to_i).to_datetime
85
122
  end
data/lib/dhc/logger.rb ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'forwardable'
5
+
6
+ class DHC::Logger < Logger
7
+ include ActiveSupport::Configurable
8
+ include Singleton
9
+
10
+ config_accessor :logger
11
+
12
+ class << self
13
+ extend Forwardable
14
+ def_delegators :instance, :log, :info, :error, :warn, :debug
15
+ end
16
+
17
+ def initialize(logdev = nil)
18
+ super
19
+ if DHC::Logger.logger
20
+ self.logger = DHC::Logger.logger
21
+ elsif defined? Rails
22
+ self.logger = Rails.logger
23
+ end
24
+ end
25
+
26
+ def self.log(severity, message = nil, progname = nil)
27
+ return if logger.blank?
28
+ logger.log(severity, message, progname)
29
+ end
30
+ end
data/lib/dhc/rspec.rb CHANGED
@@ -6,6 +6,6 @@ RSpec.configure do |config|
6
6
  config.before(:each) do
7
7
  DHC::Caching.cache = ActiveSupport::Cache::MemoryStore.new
8
8
  DHC::Caching.cache.clear
9
- DHC::Throttle.track = nil
9
+ Rails.cache.write(DHC::Throttle::CACHE_KEY, nil) if defined? Rails
10
10
  end
11
11
  end
data/lib/dhc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DHC
4
- VERSION ||= '2.0.0'
4
+ VERSION ||= '2.2.0'
5
5
  end
data/lib/dhc.rb CHANGED
@@ -72,6 +72,7 @@ module DHC
72
72
  autoload :Response, 'dhc/response'
73
73
  autoload :Rollbar, 'dhc/interceptors/rollbar'
74
74
  autoload :Zipkin, 'dhc/interceptors/zipkin'
75
+ autoload :Logger, 'dhc/logger'
75
76
 
76
77
  require 'dhc/railtie' if defined?(Rails)
77
78
  end
@@ -72,10 +72,7 @@ describe DHC::Error do
72
72
  it 'produces correct debug output' do
73
73
  expect(subject.to_s.split("\n")).to eq(<<-MSG.strip_heredoc.split("\n"))
74
74
  GET http://example.com/sessions
75
- Options: {:followlocation=>true, :auth=>{:bearer=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}, :params=>{:limit=>20}, :url=>"http://example.com/sessions"}
76
- Headers: {"Bearer Token"=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}
77
75
  Response Code: 500 (internal_error)
78
- Response Options: {:return_code=>:internal_error, :response_headers=>""}
79
76
  {"status":500,"message":"undefined"}
80
77
  The error message
81
78
  MSG
@@ -46,8 +46,8 @@ describe DHC::Caching do
46
46
  it 'serves a response from local cache without trying the central cache' do
47
47
  expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
48
48
  expect(Rails.cache).to receive(:write).and_call_original
49
- expect(-> { response_has_been_cached_and_served_from_cache! })
50
- .to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
49
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
50
+ response_has_been_cached_and_served_from_cache!
51
51
  end
52
52
  end
53
53
 
@@ -67,8 +67,8 @@ describe DHC::Caching do
67
67
  expect(redis_cache).to receive(:write).and_return(true)
68
68
  expect(Rails.cache).to receive(:fetch).and_call_original
69
69
  expect(Rails.cache).to receive(:write).and_call_original
70
- expect(-> { response_has_been_cached_and_served_from_cache! })
71
- .to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
70
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
71
+ response_has_been_cached_and_served_from_cache!
72
72
  end
73
73
  end
74
74
 
@@ -78,8 +78,8 @@ describe DHC::Caching do
78
78
  expect(redis_cache).to receive(:write).and_return(true)
79
79
  expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
80
80
  expect(Rails.cache).to receive(:write).and_call_original
81
- expect(-> { response_has_been_cached_and_served_from_cache! })
82
- .to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
81
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
82
+ response_has_been_cached_and_served_from_cache!
83
83
  end
84
84
  end
85
85
  end
@@ -97,8 +97,8 @@ describe DHC::Caching do
97
97
  expect(redis_cache).not_to receive(:write)
98
98
  expect(Rails.cache).to receive(:fetch).and_call_original
99
99
  expect(Rails.cache).to receive(:write).and_call_original
100
- expect(-> { response_has_been_cached_and_served_from_cache! })
101
- .to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
100
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
101
+ response_has_been_cached_and_served_from_cache!
102
102
  end
103
103
  end
104
104
 
@@ -115,8 +115,8 @@ describe DHC::Caching do
115
115
  expect(redis_cache).to receive(:write).and_return(true)
116
116
  expect(Rails.cache).to receive(:fetch).at_least(:once).and_call_original
117
117
  expect(Rails.cache).to receive(:write).and_call_original
118
- expect(-> { response_has_been_cached_and_served_from_cache! })
119
- .to output(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
118
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from local cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
119
+ response_has_been_cached_and_served_from_cache!
120
120
  end
121
121
  end
122
122
 
@@ -132,8 +132,8 @@ describe DHC::Caching do
132
132
  it 'does not inquire the local cache for information neither to write them' do
133
133
  expect(redis_cache).to receive(:fetch).and_return(nil, body: '<h1>Hi there</h1>', code: 200, headers: nil, return_code: nil, mock: :webmock)
134
134
  expect(redis_cache).to receive(:write).and_return(true)
135
- expect(-> { response_has_been_cached_and_served_from_cache! })
136
- .to output(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"\n}).to_stdout
135
+ expect(DHC::Logger).to receive(:info).with(%{[DHC] served from central cache: "DHC_CACHE(v1): GET http://depay.fi"}).and_call_original
136
+ response_has_been_cached_and_served_from_cache!
137
137
  end
138
138
  end
139
139
  end
@@ -25,8 +25,8 @@ describe DHC::Throttle do
25
25
  end
26
26
 
27
27
  before(:each) do
28
- DHC::Throttle.track = nil
29
28
  DHC.config.interceptors = [DHC::Throttle]
29
+ Rails.cache.write(DHC::Throttle::CACHE_KEY, nil)
30
30
 
31
31
  stub_request(:get, 'http://depay.fi').to_return(
32
32
  headers: { 'limit' => quota_limit, 'remaining' => quota_remaining, 'reset' => quota_reset }
@@ -35,8 +35,8 @@ describe DHC::Throttle do
35
35
 
36
36
  it 'tracks the request limits based on response data' do
37
37
  DHC.get('http://depay.fi', options)
38
- expect(DHC::Throttle.track[provider][:limit]).to eq quota_limit
39
- expect(DHC::Throttle.track[provider][:remaining]).to eq quota_remaining
38
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')[provider][:limit]).to eq quota_limit
39
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')[provider][:remaining]).to eq quota_remaining
40
40
  end
41
41
 
42
42
  context 'fix predefined integer for limit' do
@@ -44,7 +44,7 @@ describe DHC::Throttle do
44
44
 
45
45
  it 'tracks the limit based on initialy provided data' do
46
46
  DHC.get('http://depay.fi', options)
47
- expect(DHC::Throttle.track[provider][:limit]).to eq options_limit
47
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')[provider][:limit]).to eq options_limit
48
48
  end
49
49
  end
50
50
 
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Throttle do
6
+ let(:options) do
7
+ {
8
+ throttle: {
9
+ provider: provider,
10
+ track: true,
11
+ limit: quota_limit,
12
+ expires: 1.minute,
13
+ break: break_after
14
+ }
15
+ }
16
+ end
17
+
18
+ let(:provider) { 'depay.fi' }
19
+ let(:quota_limit) { 100 }
20
+ let(:break_after) { '80%' }
21
+
22
+ before(:each) do
23
+ DHC.config.interceptors = [DHC::Throttle]
24
+ Rails.cache.write(DHC::Throttle::CACHE_KEY, nil)
25
+
26
+ stub_request(:get, 'http://depay.fi').to_return(status: 200)
27
+ end
28
+
29
+ it 'tracks the request limits based on response data' do
30
+ DHC.get('http://depay.fi', options)
31
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')[provider][:limit]).to eq 100
32
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')[provider][:remaining]).to eq quota_limit - 1
33
+ end
34
+
35
+ context 'breaks' do
36
+ let(:quota_limit) { 10 }
37
+ let(:break_after) { '79%' }
38
+
39
+ it 'hit the breaks if throttling quota is reached' do
40
+ 8.times do
41
+ DHC.get('http://depay.fi', options)
42
+ end
43
+ expect { DHC.get('http://depay.fi', options) }.to raise_error(
44
+ DHC::Throttle::OutOfQuota,
45
+ 'Reached predefined quota for depay.fi'
46
+ )
47
+ end
48
+
49
+ context 'still within quota' do
50
+ let(:break_after) { '80%' }
51
+
52
+ it 'does not hit the breaks' do
53
+ 9.times do
54
+ DHC.get('http://depay.fi', options)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'expires' do
61
+ let(:break_after) { '80%' }
62
+ let(:quota_limit) { 10 }
63
+
64
+ it 'attempts another request if the quota expired' do
65
+ 9.times do
66
+ DHC.get('http://depay.fi', options)
67
+ end
68
+ expect { DHC.get('http://depay.fi', options) }.to raise_error(
69
+ DHC::Throttle::OutOfQuota,
70
+ 'Reached predefined quota for depay.fi'
71
+ )
72
+ Timecop.travel(Time.zone.now + 1.minute)
73
+ 9.times do
74
+ DHC.get('http://depay.fi', options)
75
+ end
76
+ expect { DHC.get('http://depay.fi', options) }.to raise_error(
77
+ DHC::Throttle::OutOfQuota,
78
+ 'Reached predefined quota for depay.fi'
79
+ )
80
+ end
81
+ end
82
+
83
+ context 'multiple provider' do
84
+ it 'tracks multiple providers without a problem' do
85
+ DHC.get('http://depay.fi', options)
86
+ stub_request(:get, 'http://depay.app').to_return(status: 200)
87
+ DHC.get('http://depay.app', {
88
+ throttle: {
89
+ provider: 'depay.app',
90
+ track: true,
91
+ limit: quota_limit,
92
+ expires: 1.minute,
93
+ break: break_after
94
+ }
95
+ })
96
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')['depay.fi']).to be_present
97
+ expect(Rails.cache.read('DHC/throttle/tracker/v1')['depay.app']).to be_present
98
+ end
99
+ end
100
+ end
@@ -23,7 +23,6 @@ describe DHC::Throttle do
23
23
  let(:expires_in) { (Time.zone.now + 1.hour).to_i }
24
24
 
25
25
  before(:each) do
26
- DHC::Throttle.track = nil
27
26
  DHC.config.interceptors = [DHC::Throttle]
28
27
 
29
28
  stub_request(:get, 'http://depay.fi')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dhc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/DePayFi/dhc/contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-21 00:00:00.000000000 Z
11
+ date: 2021-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -87,6 +87,9 @@ dependencies:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '5.2'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '7'
90
93
  type: :development
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
@@ -94,6 +97,9 @@ dependencies:
94
97
  - - ">="
95
98
  - !ruby/object:Gem::Version
96
99
  version: '5.2'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '7'
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: redis
99
105
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +237,7 @@ files:
231
237
  - lib/dhc/interceptors/rollbar.rb
232
238
  - lib/dhc/interceptors/throttle.rb
233
239
  - lib/dhc/interceptors/zipkin.rb
240
+ - lib/dhc/logger.rb
234
241
  - lib/dhc/railtie.rb
235
242
  - lib/dhc/request.rb
236
243
  - lib/dhc/response.rb
@@ -338,6 +345,7 @@ files:
338
345
  - spec/interceptors/rollbar/invalid_encoding_spec.rb
339
346
  - spec/interceptors/rollbar/main_spec.rb
340
347
  - spec/interceptors/throttle/main_spec.rb
348
+ - spec/interceptors/throttle/manually_spec.rb
341
349
  - spec/interceptors/throttle/reset_track_spec.rb
342
350
  - spec/interceptors/zipkin/distributed_tracing_spec.rb
343
351
  - spec/rails_helper.rb
@@ -391,7 +399,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
391
399
  version: '0'
392
400
  requirements:
393
401
  - Ruby >= 2.0.0
394
- rubygems_version: 3.2.3
402
+ rubygems_version: 3.2.22
395
403
  signing_key:
396
404
  specification_version: 4
397
405
  summary: Advanced HTTP Client for Ruby, fueled with interceptors
@@ -492,6 +500,7 @@ test_files:
492
500
  - spec/interceptors/rollbar/invalid_encoding_spec.rb
493
501
  - spec/interceptors/rollbar/main_spec.rb
494
502
  - spec/interceptors/throttle/main_spec.rb
503
+ - spec/interceptors/throttle/manually_spec.rb
495
504
  - spec/interceptors/throttle/reset_track_spec.rb
496
505
  - spec/interceptors/zipkin/distributed_tracing_spec.rb
497
506
  - spec/rails_helper.rb