dhc 2.0.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +25 -0
- data/dhc.gemspec +1 -1
- data/lib/dhc/interceptors/caching.rb +2 -2
- data/lib/dhc/interceptors/throttle.rb +81 -44
- data/lib/dhc/logger.rb +30 -0
- data/lib/dhc/rspec.rb +1 -1
- data/lib/dhc/version.rb +1 -1
- data/lib/dhc.rb +1 -0
- data/spec/interceptors/caching/multilevel_cache_spec.rb +12 -12
- data/spec/interceptors/throttle/main_spec.rb +4 -4
- data/spec/interceptors/throttle/manually_spec.rb +110 -0
- data/spec/interceptors/throttle/reset_track_spec.rb +0 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f70dd2da0d8ec740cf21499fc95ba815a73730c2e1c6a4b8cfef6ff18eef0ce
|
4
|
+
data.tar.gz: b0773620c07f30f040439d1c56c7a144ee2f144eb0d987d885aec2b940367b6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c652d89a8d1dcbeadf72472322881ce136692d1b51630c61f4cf0b058ff96d9ded1345c80238fa5d46599d494328ebaecc007a915283eae1971efe89de8cea6
|
7
|
+
data.tar.gz: 9f71766d909205e3771cd2cfd65130458ac6a73bf35119bd6edf83f1de1ecba418611b66544affd4572b4b275641875d6ae6507fd4a4d07ad1609ae263ff1694
|
data/.rubocop.yml
CHANGED
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'
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
35
|
-
|
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
|
39
|
-
|
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
|
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
|
57
|
-
response.headers[options
|
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
|
62
|
-
@remaining ||=
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
73
|
-
@expires ||=
|
74
|
-
|
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
|
-
|
77
|
-
|
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
|
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
data/lib/dhc/version.rb
CHANGED
data/lib/dhc.rb
CHANGED
@@ -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(
|
50
|
-
|
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(
|
71
|
-
|
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(
|
82
|
-
|
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(
|
101
|
-
|
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(
|
119
|
-
|
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(
|
136
|
-
|
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
|
39
|
-
expect(DHC
|
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
|
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,110 @@
|
|
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) { 100 }
|
37
|
+
let(:break_after) { '79%' }
|
38
|
+
|
39
|
+
it 'hit the breaks if throttling quota is reached' do
|
40
|
+
79.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
|
+
80.times do
|
54
|
+
DHC.get('http://depay.fi', options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does hit the breaks surpassing quota' do
|
59
|
+
80.times do
|
60
|
+
DHC.get('http://depay.fi', options)
|
61
|
+
end
|
62
|
+
expect { DHC.get('http://depay.fi', options) }.to raise_error(
|
63
|
+
DHC::Throttle::OutOfQuota,
|
64
|
+
'Reached predefined quota for depay.fi'
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'expires' do
|
71
|
+
let(:break_after) { '80%' }
|
72
|
+
let(:quota_limit) { 100 }
|
73
|
+
|
74
|
+
it 'attempts another request if the quota expired' do
|
75
|
+
80.times do
|
76
|
+
DHC.get('http://depay.fi', options)
|
77
|
+
end
|
78
|
+
expect { DHC.get('http://depay.fi', options) }.to raise_error(
|
79
|
+
DHC::Throttle::OutOfQuota,
|
80
|
+
'Reached predefined quota for depay.fi'
|
81
|
+
)
|
82
|
+
Timecop.travel(Time.zone.now + 1.minute)
|
83
|
+
80.times do
|
84
|
+
DHC.get('http://depay.fi', options)
|
85
|
+
end
|
86
|
+
expect { DHC.get('http://depay.fi', options) }.to raise_error(
|
87
|
+
DHC::Throttle::OutOfQuota,
|
88
|
+
'Reached predefined quota for depay.fi'
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'multiple provider' do
|
94
|
+
it 'tracks multiple providers without a problem' do
|
95
|
+
DHC.get('http://depay.fi', options)
|
96
|
+
stub_request(:get, 'http://depay.app').to_return(status: 200)
|
97
|
+
DHC.get('http://depay.app', {
|
98
|
+
throttle: {
|
99
|
+
provider: 'depay.app',
|
100
|
+
track: true,
|
101
|
+
limit: quota_limit,
|
102
|
+
expires: 1.minute,
|
103
|
+
break: break_after
|
104
|
+
}
|
105
|
+
})
|
106
|
+
expect(Rails.cache.read('DHC/throttle/tracker/v1')['depay.fi']).to be_present
|
107
|
+
expect(Rails.cache.read('DHC/throttle/tracker/v1')['depay.app']).to be_present
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
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.
|
4
|
+
version: 2.2.1
|
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-12-
|
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
|
@@ -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
|