berater 0.8.0 → 0.9.0
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/lib/berater.rb +15 -2
- data/lib/berater/limiter.rb +40 -24
- data/lib/berater/limiter_set.rb +66 -0
- data/lib/berater/version.rb +1 -1
- data/spec/berater_spec.rb +18 -0
- data/spec/limiter_set_spec.rb +173 -0
- data/spec/limiter_spec.rb +31 -2
- data/spec/middleware_spec.rb +110 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 476b59e3f1e27908f5c8a5097087e6c8c2384531e1284d79b9d89a73fbbb5840
|
4
|
+
data.tar.gz: de50fdcab6ea7dc9520fcf1aefdd07b1f8775c0ce96a30e3f1d45b6ccfb7b00f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2446e64f528a8ef1d37791922d37cddcebdf702f3c5beff2ef7ea9d611ce4cc6d6c40ac42e1ea826987a2eb2ceea3ddf97e420bb7369686b8239b260a1725c55
|
7
|
+
data.tar.gz: 23dccad7e02cc425631ceeb1dfbc6960b94ac92c523d840a991917af02caaf39a7befc5887fe45631f565ddb2eddb4850e557348ab29427d3cbae1db89124c3c
|
data/lib/berater.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'berater/limiter'
|
2
|
+
require 'berater/limiter_set'
|
2
3
|
require 'berater/lock'
|
3
4
|
require 'berater/lua_script'
|
4
5
|
require 'berater/utils'
|
5
6
|
require 'berater/version'
|
7
|
+
require 'meddleware'
|
6
8
|
|
7
9
|
module Berater
|
8
10
|
extend self
|
@@ -15,8 +17,14 @@ module Berater
|
|
15
17
|
yield self
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
19
|
-
@
|
20
|
+
def limiters
|
21
|
+
@limiters ||= LimiterSet.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def middleware(&block)
|
25
|
+
(@middleware ||= Meddleware.new).tap do
|
26
|
+
@middleware.instance_eval(&block) if block_given?
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
def new(key, capacity, **opts)
|
@@ -48,6 +56,11 @@ module Berater
|
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
59
|
+
def reset
|
60
|
+
@redis = nil
|
61
|
+
limiters.clear
|
62
|
+
middleware.clear
|
63
|
+
end
|
51
64
|
end
|
52
65
|
|
53
66
|
# convenience method
|
data/lib/berater/limiter.rb
CHANGED
@@ -9,17 +9,12 @@ module Berater
|
|
9
9
|
|
10
10
|
def limit(capacity: nil, cost: 1, &block)
|
11
11
|
capacity ||= @capacity
|
12
|
+
lock = nil
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
Berater.middleware.call(self, capacity: capacity, cost: cost) do |limiter, **opts|
|
15
|
+
lock = limiter.inner_limit(**opts)
|
15
16
|
end
|
16
17
|
|
17
|
-
unless cost.is_a?(Numeric) && cost >= 0 && cost < Float::INFINITY
|
18
|
-
raise ArgumentError, "invalid cost: #{cost}"
|
19
|
-
end
|
20
|
-
|
21
|
-
lock = acquire_lock(capacity, cost)
|
22
|
-
|
23
18
|
if block_given?
|
24
19
|
begin
|
25
20
|
yield lock
|
@@ -31,6 +26,23 @@ module Berater
|
|
31
26
|
end
|
32
27
|
end
|
33
28
|
|
29
|
+
protected def inner_limit(capacity:, cost:)
|
30
|
+
unless capacity.is_a?(Numeric) && capacity >= 0
|
31
|
+
raise ArgumentError, "invalid capacity: #{capacity}"
|
32
|
+
end
|
33
|
+
|
34
|
+
unless cost.is_a?(Numeric) && cost >= 0 && cost < Float::INFINITY
|
35
|
+
raise ArgumentError, "invalid cost: #{cost}"
|
36
|
+
end
|
37
|
+
|
38
|
+
acquire_lock(capacity, cost)
|
39
|
+
rescue NoMethodError => e
|
40
|
+
raise unless e.message.include?("undefined method `evalsha' for")
|
41
|
+
|
42
|
+
# repackage error so it's easier to understand
|
43
|
+
raise RuntimeError, "invalid redis connection: #{redis}"
|
44
|
+
end
|
45
|
+
|
34
46
|
def utilization
|
35
47
|
lock = limit(cost: 0)
|
36
48
|
|
@@ -52,13 +64,6 @@ module Berater
|
|
52
64
|
self.redis.connection == other.redis.connection
|
53
65
|
end
|
54
66
|
|
55
|
-
def self.new(*)
|
56
|
-
# can only call via subclass
|
57
|
-
raise NoMethodError if self == Berater::Limiter
|
58
|
-
|
59
|
-
super
|
60
|
-
end
|
61
|
-
|
62
67
|
protected
|
63
68
|
|
64
69
|
attr_reader :args
|
@@ -93,16 +98,27 @@ module Berater
|
|
93
98
|
self.class.cache_key(instance_key)
|
94
99
|
end
|
95
100
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
101
|
+
class << self
|
102
|
+
def new(*)
|
103
|
+
# can only call via subclass
|
104
|
+
raise NoMethodError if self == Berater::Limiter
|
105
|
+
|
106
|
+
super
|
107
|
+
end
|
100
108
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
109
|
+
def cache_key(key)
|
110
|
+
klass = to_s.split(':')[-1]
|
111
|
+
"Berater:#{klass}:#{key}"
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
def inherited(subclass)
|
117
|
+
# automagically create convenience method
|
118
|
+
name = subclass.to_s.split(':')[-1]
|
119
|
+
Berater.define_singleton_method(name) do |*args, **opts, &block|
|
120
|
+
Berater::Utils.convenience_fn(subclass, *args, **opts, &block)
|
121
|
+
end
|
106
122
|
end
|
107
123
|
end
|
108
124
|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Berater
|
2
|
+
private
|
3
|
+
|
4
|
+
class LimiterSet
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@limiters = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def each(&block)
|
12
|
+
@limiters.each_value(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(limiter)
|
16
|
+
key = limiter.key if limiter.respond_to?(:key)
|
17
|
+
send(:[]=, key, limiter)
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(key, limiter)
|
21
|
+
unless limiter.is_a? Berater::Limiter
|
22
|
+
raise ArgumentError, "expected Berater::Limiter, found: #{limiter}"
|
23
|
+
end
|
24
|
+
|
25
|
+
@limiters[key] = limiter
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](key)
|
29
|
+
@limiters[key]
|
30
|
+
end
|
31
|
+
|
32
|
+
def fetch(key, val = default = true, &block)
|
33
|
+
args = default ? [ key ] : [ key, val ]
|
34
|
+
@limiters.fetch(*args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def include?(key)
|
38
|
+
if key.is_a? Berater::Limiter
|
39
|
+
@limiters.value?(key)
|
40
|
+
else
|
41
|
+
@limiters.key?(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def clear
|
46
|
+
@limiters.clear
|
47
|
+
end
|
48
|
+
|
49
|
+
def count
|
50
|
+
@limiters.count
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete(key)
|
54
|
+
if key.is_a? Berater::Limiter
|
55
|
+
@limiters.delete(key.key)
|
56
|
+
else
|
57
|
+
@limiters.delete(key)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
alias remove delete
|
61
|
+
|
62
|
+
def empty?
|
63
|
+
@limiters.empty?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/berater/version.rb
CHANGED
data/spec/berater_spec.rb
CHANGED
@@ -24,6 +24,24 @@ describe Berater do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
describe '.limiters' do
|
28
|
+
subject { Berater.limiters }
|
29
|
+
|
30
|
+
let(:limiter) { Berater(:key, 1) }
|
31
|
+
|
32
|
+
it 'provides access to predefined limiters' do
|
33
|
+
expect(Berater.limiters).to be_a Berater::LimiterSet
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'resets with Berater' do
|
37
|
+
subject << limiter
|
38
|
+
is_expected.not_to be_empty
|
39
|
+
|
40
|
+
Berater.reset
|
41
|
+
is_expected.to be_empty
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
27
45
|
shared_examples 'a Berater' do |klass, capacity, **opts|
|
28
46
|
describe '.new' do
|
29
47
|
let(:limiter) { Berater.new(:key, capacity, **opts) }
|
@@ -0,0 +1,173 @@
|
|
1
|
+
describe Berater::LimiterSet do
|
2
|
+
subject { described_class.new }
|
3
|
+
|
4
|
+
let(:unlimiter) { Berater::Unlimiter.new }
|
5
|
+
let(:inhibitor) { Berater::Inhibitor.new }
|
6
|
+
|
7
|
+
describe '#each' do
|
8
|
+
it 'returns an Enumerator' do
|
9
|
+
expect(subject.each).to be_a Enumerator
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'works with an empty set' do
|
13
|
+
expect(subject.each.to_a).to eq []
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns elements' do
|
17
|
+
subject << unlimiter
|
18
|
+
expect(subject.each.to_a).to eq [ unlimiter ]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#<<' do
|
23
|
+
it 'adds a limiter' do
|
24
|
+
subject << unlimiter
|
25
|
+
expect(subject.each.to_a).to eq [ unlimiter ]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'rejects things that are not limiters' do
|
29
|
+
expect {
|
30
|
+
subject << :foo
|
31
|
+
}.to raise_error(ArgumentError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'updates existing keys' do
|
35
|
+
limiter = Berater::Unlimiter.new
|
36
|
+
expect(limiter).to eq unlimiter
|
37
|
+
expect(limiter).not_to be unlimiter
|
38
|
+
|
39
|
+
subject << unlimiter
|
40
|
+
subject << limiter
|
41
|
+
|
42
|
+
expect(subject.each.to_a).to eq [ limiter ]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '[]=' do
|
47
|
+
it 'adds a limiter' do
|
48
|
+
subject[:key] = unlimiter
|
49
|
+
|
50
|
+
expect(subject.each.to_a).to eq [ unlimiter ]
|
51
|
+
is_expected.to include :key
|
52
|
+
is_expected.to include unlimiter
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'rejects things that are not limiters' do
|
56
|
+
expect {
|
57
|
+
subject[:key] = :foo
|
58
|
+
}.to raise_error(ArgumentError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#[]' do
|
63
|
+
it 'returns nil for missing keys' do
|
64
|
+
expect(subject[:key]).to be nil
|
65
|
+
expect(subject[nil]).to be nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'retreives limiters' do
|
69
|
+
subject << unlimiter
|
70
|
+
expect(subject[unlimiter.key]).to be unlimiter
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#fetch' do
|
75
|
+
it 'raises for missing keys' do
|
76
|
+
expect {
|
77
|
+
subject.fetch(:key)
|
78
|
+
}.to raise_error(KeyError)
|
79
|
+
|
80
|
+
expect {
|
81
|
+
subject.fetch(nil)
|
82
|
+
}.to raise_error(KeyError)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns the default if provided' do
|
86
|
+
expect(subject.fetch(:key, unlimiter)).to be unlimiter
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'calls the default proc if provided' do
|
90
|
+
expect {|block| subject.fetch(:key, &block) }.to yield_control
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'retreives limiters' do
|
94
|
+
subject << unlimiter
|
95
|
+
expect(subject.fetch(unlimiter.key)).to be unlimiter
|
96
|
+
expect(subject.fetch(unlimiter.key, :default)).to be unlimiter
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#include?' do
|
101
|
+
before do
|
102
|
+
subject << unlimiter
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'works with keys' do
|
106
|
+
is_expected.to include unlimiter.key
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'works with limiters' do
|
110
|
+
is_expected.to include unlimiter
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'works when target is missing' do
|
114
|
+
is_expected.not_to include inhibitor.key
|
115
|
+
is_expected.not_to include inhibitor
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#clear' do
|
120
|
+
it 'works when empty' do
|
121
|
+
subject.clear
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'clears limiters' do
|
125
|
+
subject << unlimiter
|
126
|
+
is_expected.to include unlimiter
|
127
|
+
|
128
|
+
subject.clear
|
129
|
+
is_expected.not_to include unlimiter
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#count' do
|
134
|
+
it 'counts' do
|
135
|
+
expect(subject.count).to be 0
|
136
|
+
|
137
|
+
subject << unlimiter
|
138
|
+
expect(subject.count).to be 1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#delete' do
|
143
|
+
it 'works when the target is missing' do
|
144
|
+
subject.delete(unlimiter)
|
145
|
+
subject.delete(unlimiter.key)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'works with keys' do
|
149
|
+
subject << unlimiter
|
150
|
+
is_expected.to include unlimiter
|
151
|
+
|
152
|
+
subject.delete(unlimiter.key)
|
153
|
+
is_expected.not_to include unlimiter
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'works with limiters' do
|
157
|
+
subject << unlimiter
|
158
|
+
is_expected.to include unlimiter
|
159
|
+
|
160
|
+
subject.delete(unlimiter)
|
161
|
+
is_expected.not_to include unlimiter
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#empty?' do
|
166
|
+
it 'works' do
|
167
|
+
is_expected.to be_empty
|
168
|
+
|
169
|
+
subject << unlimiter
|
170
|
+
is_expected.not_to be_empty
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
data/spec/limiter_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
describe Berater::Limiter do
|
2
|
-
|
3
|
-
|
2
|
+
describe '.new' do
|
3
|
+
it 'can only be called on subclasses' do
|
4
|
+
expect { described_class.new }.to raise_error(NoMethodError)
|
5
|
+
end
|
4
6
|
end
|
5
7
|
|
6
8
|
describe 'abstract methods' do
|
@@ -50,6 +52,33 @@ describe Berater::Limiter do
|
|
50
52
|
}.to raise_error(ArgumentError)
|
51
53
|
end
|
52
54
|
end
|
55
|
+
|
56
|
+
context 'when Berater.redis is nil' do
|
57
|
+
let!(:redis) { Berater.redis }
|
58
|
+
|
59
|
+
before { Berater.redis = nil }
|
60
|
+
|
61
|
+
it 'works with Unlimiter since redis is not used' do
|
62
|
+
expect(subject.redis).to be nil
|
63
|
+
expect {|b| subject.limit(&b) }.to yield_control
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises when redis is needed' do
|
67
|
+
limiter = Berater::RateLimiter.new(:key, 1, :second)
|
68
|
+
expect(limiter.redis).to be nil
|
69
|
+
expect { limiter.limit }.to raise_error(RuntimeError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'works when redis is passed in' do
|
73
|
+
limiter = Berater::RateLimiter.new(:key, 1, :second, redis: redis)
|
74
|
+
expect {|b| limiter.limit(&b) }.to yield_control
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'raises when redis is bogus' do
|
78
|
+
limiter = Berater::RateLimiter.new(:key, 1, :second, redis: :stub)
|
79
|
+
expect { limiter.limit }.to raise_error(RuntimeError)
|
80
|
+
end
|
81
|
+
end
|
53
82
|
end
|
54
83
|
|
55
84
|
describe '#==' do
|
@@ -0,0 +1,110 @@
|
|
1
|
+
class Meddler
|
2
|
+
def call(*)
|
3
|
+
yield
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
describe 'Berater.middleware' do
|
8
|
+
subject { Berater.middleware }
|
9
|
+
|
10
|
+
describe 'adding middleware' do
|
11
|
+
after { is_expected.to include Meddler }
|
12
|
+
|
13
|
+
it 'can be done inline' do
|
14
|
+
Berater.middleware.use Meddler
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can be done with a block' do
|
18
|
+
Berater.middleware do
|
19
|
+
use Meddler
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'resets along with Berater' do
|
25
|
+
Berater.middleware.use Meddler
|
26
|
+
is_expected.to include Meddler
|
27
|
+
|
28
|
+
Berater.reset
|
29
|
+
is_expected.to be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'Berater::Limiter#limit' do
|
33
|
+
let(:middleware) { Meddler.new }
|
34
|
+
let(:limiter) { Berater::ConcurrencyLimiter.new(:key, 1) }
|
35
|
+
|
36
|
+
before do
|
37
|
+
expect(Meddler).to receive(:new).and_return(middleware).at_least(1)
|
38
|
+
Berater.middleware.use Meddler
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'calls the middleware' do
|
42
|
+
expect(middleware).to receive(:call)
|
43
|
+
limiter.limit
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'calls the middleware, passing the limiter and options' do
|
47
|
+
expect(middleware).to receive(:call).with(
|
48
|
+
limiter,
|
49
|
+
hash_including(:capacity, :cost)
|
50
|
+
)
|
51
|
+
|
52
|
+
limiter.limit
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when used per ususual' do
|
56
|
+
before do
|
57
|
+
expect(middleware).to receive(:call).and_call_original.at_least(1)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'still works inline' do
|
61
|
+
expect(limiter.limit).to be_a Berater::Lock
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'still works in block mode' do
|
65
|
+
expect(limiter.limit { 123 }).to be 123
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'still has limits' do
|
69
|
+
limiter.limit
|
70
|
+
expect(limiter).to be_overloaded
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when middleware meddles' do
|
75
|
+
it 'can change the capacity' do
|
76
|
+
expect(middleware).to receive(:call) do |limiter, opts, &block|
|
77
|
+
opts[:capacity] = 0
|
78
|
+
block.call
|
79
|
+
end
|
80
|
+
|
81
|
+
expect { limiter.limit }.to be_overloaded
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'can change the cost' do
|
85
|
+
expect(middleware).to receive(:call) do |limiter, opts, &block|
|
86
|
+
opts[:cost] = 2
|
87
|
+
block.call
|
88
|
+
end
|
89
|
+
|
90
|
+
expect { limiter.limit }.to be_overloaded
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'can change the limiter' do
|
94
|
+
other_limiter = Berater::Inhibitor.new
|
95
|
+
|
96
|
+
expect(middleware).to receive(:call) do |limiter, opts, &block|
|
97
|
+
block.call other_limiter, opts
|
98
|
+
end
|
99
|
+
expect(other_limiter).to receive(:acquire_lock).and_call_original
|
100
|
+
|
101
|
+
expect { limiter.limit }.to be_overloaded
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'can abort by not yielding' do
|
105
|
+
expect(middleware).to receive(:call)
|
106
|
+
expect(limiter.limit).to be nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: berater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Pepper
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: meddleware
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: redis
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,6 +147,7 @@ files:
|
|
133
147
|
- lib/berater/dsl.rb
|
134
148
|
- lib/berater/inhibitor.rb
|
135
149
|
- lib/berater/limiter.rb
|
150
|
+
- lib/berater/limiter_set.rb
|
136
151
|
- lib/berater/lock.rb
|
137
152
|
- lib/berater/lua_script.rb
|
138
153
|
- lib/berater/rate_limiter.rb
|
@@ -148,9 +163,11 @@ files:
|
|
148
163
|
- spec/dsl_refinement_spec.rb
|
149
164
|
- spec/dsl_spec.rb
|
150
165
|
- spec/inhibitor_spec.rb
|
166
|
+
- spec/limiter_set_spec.rb
|
151
167
|
- spec/limiter_spec.rb
|
152
168
|
- spec/lua_script_spec.rb
|
153
169
|
- spec/matchers_spec.rb
|
170
|
+
- spec/middleware_spec.rb
|
154
171
|
- spec/rate_limiter_spec.rb
|
155
172
|
- spec/riddle_spec.rb
|
156
173
|
- spec/static_limiter_spec.rb
|
@@ -185,10 +202,12 @@ test_files:
|
|
185
202
|
- spec/matchers_spec.rb
|
186
203
|
- spec/dsl_refinement_spec.rb
|
187
204
|
- spec/test_mode_spec.rb
|
205
|
+
- spec/middleware_spec.rb
|
188
206
|
- spec/dsl_spec.rb
|
189
207
|
- spec/lua_script_spec.rb
|
190
208
|
- spec/concurrency_limiter_spec.rb
|
191
209
|
- spec/riddle_spec.rb
|
210
|
+
- spec/limiter_set_spec.rb
|
192
211
|
- spec/utils_spec.rb
|
193
212
|
- spec/berater_spec.rb
|
194
213
|
- spec/limiter_spec.rb
|