berater 0.1.0 → 0.2.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 +17 -24
- data/lib/berater/base_limiter.rb +11 -19
- data/lib/berater/concurrency_limiter.rb +28 -88
- data/lib/berater/inhibitor.rb +3 -9
- data/lib/berater/lock.rb +36 -0
- data/lib/berater/rate_limiter.rb +14 -16
- data/lib/berater/unlimiter.rb +14 -9
- data/lib/berater/version.rb +1 -1
- data/spec/berater_spec.rb +31 -98
- data/spec/concurrency_limiter_spec.rb +58 -73
- data/spec/concurrency_lock_spec.rb +26 -21
- data/spec/inhibitor_spec.rb +3 -15
- data/spec/matcher_spec.rb +4 -4
- data/spec/rate_limiter_spec.rb +27 -50
- data/spec/rate_lock_spec.rb +20 -0
- data/spec/unlimiter_spec.rb +7 -31
- metadata +5 -2
data/spec/inhibitor_spec.rb
CHANGED
@@ -1,36 +1,24 @@
|
|
1
1
|
describe Berater::Inhibitor do
|
2
|
-
before { Berater.mode = :inhibited }
|
3
|
-
|
4
2
|
describe '.new' do
|
5
3
|
it 'initializes without any arguments or options' do
|
6
4
|
expect(described_class.new).to be_a described_class
|
7
5
|
end
|
8
6
|
|
9
7
|
it 'initializes with any arguments and options' do
|
10
|
-
expect(described_class.new(:abc, x: 123)).to be_a described_class
|
8
|
+
expect(described_class.new(:abc, :def, x: 123)).to be_a described_class
|
11
9
|
end
|
12
10
|
|
13
11
|
it 'has default values' do
|
14
|
-
expect(described_class.new.key).to
|
12
|
+
expect(described_class.new.key).to be :inhibitor
|
15
13
|
expect(described_class.new.redis).to be Berater.redis
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
describe '.limit' do
|
20
|
-
it 'always limits' do
|
21
|
-
expect { described_class.limit }.to be_inhibited
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'works with any arguments or options' do
|
25
|
-
expect { described_class.limit(:abc, x: 123) }.to be_inhibited
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
17
|
describe '#limit' do
|
30
18
|
let(:limiter) { described_class.new }
|
31
19
|
|
32
20
|
it 'always limits' do
|
33
|
-
expect {
|
21
|
+
expect { limiter.limit }.to be_inhibited
|
34
22
|
end
|
35
23
|
end
|
36
24
|
|
data/spec/matcher_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
describe 'be_overloaded' do
|
2
2
|
context 'Berater::Unlimiter' do
|
3
|
-
let(:limiter) { Berater.new(:unlimited) }
|
3
|
+
let(:limiter) { Berater.new(:key, :unlimited) }
|
4
4
|
|
5
5
|
it { expect(limiter).not_to be_overloaded }
|
6
6
|
it { expect(limiter).not_to be_inhibited }
|
@@ -19,7 +19,7 @@ describe 'be_overloaded' do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'Berater::Inhibitor' do
|
22
|
-
let(:limiter) { Berater.new(:inhibited) }
|
22
|
+
let(:limiter) { Berater.new(:key, :inhibited) }
|
23
23
|
|
24
24
|
it { expect(limiter).to be_overloaded }
|
25
25
|
it { expect(limiter).to be_inhibited }
|
@@ -32,7 +32,7 @@ describe 'be_overloaded' do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
context 'Berater::RateLimiter' do
|
35
|
-
let(:limiter) { Berater.new(:rate, 1, :second) }
|
35
|
+
let(:limiter) { Berater.new(:key, :rate, 1, :second) }
|
36
36
|
|
37
37
|
it { expect(limiter).not_to be_overloaded }
|
38
38
|
it { expect(limiter).not_to be_inhibited }
|
@@ -67,7 +67,7 @@ describe 'be_overloaded' do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
context 'Berater::ConcurrencyLimiter' do
|
70
|
-
let(:limiter) { Berater.new(:concurrency, 1) }
|
70
|
+
let(:limiter) { Berater.new(:key, :concurrency, 1) }
|
71
71
|
|
72
72
|
it { expect(limiter).not_to be_overloaded }
|
73
73
|
it { expect(limiter).not_to be_inhibited }
|
data/spec/rate_limiter_spec.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
describe Berater::RateLimiter do
|
2
|
-
before { Berater.mode = :rate }
|
3
2
|
|
4
3
|
describe '.new' do
|
5
|
-
let(:limiter) { described_class.new(1, :second) }
|
4
|
+
let(:limiter) { described_class.new(:key, 1, :second) }
|
6
5
|
|
7
6
|
it 'initializes' do
|
7
|
+
expect(limiter.key).to be :key
|
8
8
|
expect(limiter.count).to eq 1
|
9
9
|
expect(limiter.interval).to eq 1
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'has default values' do
|
13
|
-
expect(limiter.key).to eq described_class.to_s
|
14
13
|
expect(limiter.redis).to be Berater.redis
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
17
|
describe '#count' do
|
19
18
|
def expect_count(count)
|
20
|
-
limiter = described_class.new(count, :second)
|
19
|
+
limiter = described_class.new(:key, count, :second)
|
21
20
|
expect(limiter.count).to eq count
|
22
21
|
end
|
23
22
|
|
@@ -28,7 +27,7 @@ describe Berater::RateLimiter do
|
|
28
27
|
context 'with erroneous values' do
|
29
28
|
def expect_bad_count(count)
|
30
29
|
expect do
|
31
|
-
described_class.new(count, :second)
|
30
|
+
described_class.new(:key, count, :second)
|
32
31
|
end.to raise_error ArgumentError
|
33
32
|
end
|
34
33
|
|
@@ -41,7 +40,7 @@ describe Berater::RateLimiter do
|
|
41
40
|
|
42
41
|
describe '#interval' do
|
43
42
|
def expect_interval(interval, expected)
|
44
|
-
limiter = described_class.new(1, interval)
|
43
|
+
limiter = described_class.new(:key, 1, interval)
|
45
44
|
expect(limiter.interval).to eq expected
|
46
45
|
end
|
47
46
|
|
@@ -73,7 +72,7 @@ describe Berater::RateLimiter do
|
|
73
72
|
context 'with erroneous values' do
|
74
73
|
def expect_bad_interval(interval)
|
75
74
|
expect do
|
76
|
-
described_class.new(1, interval)
|
75
|
+
described_class.new(:key, 1, interval)
|
77
76
|
end.to raise_error(ArgumentError)
|
78
77
|
end
|
79
78
|
|
@@ -84,82 +83,60 @@ describe Berater::RateLimiter do
|
|
84
83
|
end
|
85
84
|
|
86
85
|
describe '#limit' do
|
87
|
-
let(:limiter) { described_class.new(3, :second) }
|
86
|
+
let(:limiter) { described_class.new(:key, 3, :second) }
|
88
87
|
|
89
88
|
it 'works' do
|
90
|
-
expect(limiter.limit).to eq 1
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'counts' do
|
94
|
-
expect(limiter.limit).to eq 1
|
95
|
-
expect(limiter.limit).to eq 2
|
96
|
-
expect(limiter.limit).to eq 3
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'yields' do
|
100
89
|
expect {|b| limiter.limit(&b) }.to yield_control
|
101
90
|
expect(limiter.limit { 123 }).to eq 123
|
102
91
|
end
|
103
92
|
|
93
|
+
it 'works without a block' do
|
94
|
+
expect(limiter.limit).to be_a Berater::Lock
|
95
|
+
end
|
96
|
+
|
104
97
|
it 'limits excessive calls' do
|
105
98
|
3.times { limiter.limit }
|
106
99
|
|
107
|
-
expect
|
100
|
+
expect(limiter).to be_overrated
|
108
101
|
end
|
109
102
|
|
110
103
|
it 'limit resets over time' do
|
111
|
-
|
112
|
-
expect(limiter.limit).to eq 2
|
113
|
-
expect(limiter.limit).to eq 3
|
104
|
+
3.times { limiter.limit }
|
114
105
|
expect(limiter).to be_overrated
|
115
106
|
|
116
107
|
# travel forward a second
|
117
108
|
Timecop.freeze(1)
|
118
109
|
|
119
|
-
|
120
|
-
expect(limiter.limit).to eq 2
|
121
|
-
expect(limiter.limit).to eq 3
|
110
|
+
3.times { limiter.limit }
|
122
111
|
expect(limiter).to be_overrated
|
123
112
|
end
|
124
113
|
end
|
125
114
|
|
126
115
|
context 'with same key, different limiters' do
|
127
|
-
let(:limiter_one) { described_class.new(1, :second) }
|
128
|
-
let(:limiter_two) { described_class.new(1, :second) }
|
129
|
-
|
130
|
-
it 'works as expected' do
|
131
|
-
expect(limiter_one.limit).to eq 1
|
132
|
-
|
133
|
-
expect { limiter_one }.to be_overrated
|
134
|
-
expect { limiter_two }.to be_overrated
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
context 'with different keys, same limiter' do
|
139
|
-
let(:limiter) { described_class.new(1, :second) }
|
116
|
+
let(:limiter_one) { described_class.new(:key, 1, :second) }
|
117
|
+
let(:limiter_two) { described_class.new(:key, 1, :second) }
|
140
118
|
|
141
119
|
it 'works as expected' do
|
142
|
-
expect
|
143
|
-
expect { limiter.limit(key: :one) }.to be_overrated
|
120
|
+
expect(limiter_one.limit).not_to be_overrated
|
144
121
|
|
145
|
-
expect
|
146
|
-
expect
|
122
|
+
expect(limiter_one).to be_overrated
|
123
|
+
expect(limiter_two).to be_overrated
|
147
124
|
end
|
148
125
|
end
|
149
126
|
|
150
127
|
context 'with different keys, different limiters' do
|
151
|
-
let(:limiter_one) { described_class.new(1, :second
|
152
|
-
let(:limiter_two) { described_class.new(2, :second
|
128
|
+
let(:limiter_one) { described_class.new(:one, 1, :second) }
|
129
|
+
let(:limiter_two) { described_class.new(:two, 2, :second) }
|
153
130
|
|
154
131
|
it 'works as expected' do
|
155
|
-
expect(limiter_one.limit).
|
156
|
-
expect(limiter_two.limit).
|
132
|
+
expect(limiter_one.limit).not_to be_overrated
|
133
|
+
expect(limiter_two.limit).not_to be_overrated
|
157
134
|
|
158
|
-
expect
|
159
|
-
expect(limiter_two.limit).
|
135
|
+
expect(limiter_one).to be_overrated
|
136
|
+
expect(limiter_two.limit).not_to be_overrated
|
160
137
|
|
161
|
-
expect
|
162
|
-
expect
|
138
|
+
expect(limiter_one).to be_overrated
|
139
|
+
expect(limiter_two).to be_overrated
|
163
140
|
end
|
164
141
|
end
|
165
142
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
describe Berater::Lock do
|
2
|
+
it_behaves_like 'a lock', Berater.new(:key, :rate, 3, :second)
|
3
|
+
|
4
|
+
let(:limiter) { Berater.new(:key, :rate, 3, :second) }
|
5
|
+
|
6
|
+
describe '#expired?' do
|
7
|
+
let!(:lock) { limiter.limit }
|
8
|
+
|
9
|
+
it 'never expires' do
|
10
|
+
expect(lock.locked?).to be true
|
11
|
+
expect(lock.expired?).to be false
|
12
|
+
|
13
|
+
Timecop.travel(1_000)
|
14
|
+
|
15
|
+
expect(lock.locked?).to be true
|
16
|
+
expect(lock.expired?).to be false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/spec/unlimiter_spec.rb
CHANGED
@@ -1,50 +1,28 @@
|
|
1
1
|
describe Berater::Unlimiter do
|
2
|
-
before { Berater.mode = :unlimited }
|
3
|
-
|
4
2
|
describe '.new' do
|
5
3
|
it 'initializes without any arguments or options' do
|
6
4
|
expect(described_class.new).to be_a described_class
|
7
5
|
end
|
8
6
|
|
9
7
|
it 'initializes with any arguments and options' do
|
10
|
-
expect(described_class.new(:abc, x: 123)).to be_a described_class
|
8
|
+
expect(described_class.new(:abc, :def, x: 123)).to be_a described_class
|
11
9
|
end
|
12
10
|
|
13
11
|
it 'has default values' do
|
14
|
-
expect(described_class.new.key).to
|
12
|
+
expect(described_class.new.key).to be :unlimiter
|
15
13
|
expect(described_class.new.redis).to be Berater.redis
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
describe '.limit' do
|
20
|
-
it 'works' do
|
21
|
-
expect(described_class.limit).to be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'yields' do
|
25
|
-
expect {|b| described_class.limit(&b) }.to yield_control
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'is never overloaded' do
|
29
|
-
10.times do
|
30
|
-
expect { described_class.limit }.not_to be_overloaded
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'works with any arguments or options' do
|
35
|
-
expect(described_class.limit(:abc, x: 123)).to be_nil
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
17
|
describe '#limit' do
|
40
18
|
let(:limiter) { described_class.new }
|
41
19
|
|
42
20
|
it 'works' do
|
43
|
-
expect
|
21
|
+
expect {|b| limiter.limit(&b) }.to yield_control
|
44
22
|
end
|
45
23
|
|
46
|
-
it '
|
47
|
-
expect
|
24
|
+
it 'works without a block' do
|
25
|
+
expect(limiter.limit).to be_a Berater::Lock
|
48
26
|
end
|
49
27
|
|
50
28
|
it 'is never overloaded' do
|
@@ -52,10 +30,8 @@ describe Berater::Unlimiter do
|
|
52
30
|
expect { limiter.limit }.not_to be_overloaded
|
53
31
|
end
|
54
32
|
end
|
55
|
-
|
56
|
-
it 'works with any arguments or options' do
|
57
|
-
expect(limiter.limit(x: 123)).to be_nil
|
58
|
-
end
|
59
33
|
end
|
60
34
|
|
35
|
+
it_behaves_like 'a lock', described_class.new
|
36
|
+
|
61
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: berater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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-02-
|
11
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/berater/base_limiter.rb
|
119
119
|
- lib/berater/concurrency_limiter.rb
|
120
120
|
- lib/berater/inhibitor.rb
|
121
|
+
- lib/berater/lock.rb
|
121
122
|
- lib/berater/rate_limiter.rb
|
122
123
|
- lib/berater/unlimiter.rb
|
123
124
|
- lib/berater/version.rb
|
@@ -127,6 +128,7 @@ files:
|
|
127
128
|
- spec/inhibitor_spec.rb
|
128
129
|
- spec/matcher_spec.rb
|
129
130
|
- spec/rate_limiter_spec.rb
|
131
|
+
- spec/rate_lock_spec.rb
|
130
132
|
- spec/unlimiter_spec.rb
|
131
133
|
homepage: https://github.com/dpep/berater_rb
|
132
134
|
licenses:
|
@@ -154,6 +156,7 @@ summary: Berater
|
|
154
156
|
test_files:
|
155
157
|
- spec/rate_limiter_spec.rb
|
156
158
|
- spec/matcher_spec.rb
|
159
|
+
- spec/rate_lock_spec.rb
|
157
160
|
- spec/concurrency_limiter_spec.rb
|
158
161
|
- spec/concurrency_lock_spec.rb
|
159
162
|
- spec/berater_spec.rb
|