redis-throttler 0.1.6 → 0.1.7

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
  SHA1:
3
- metadata.gz: aee41934ea93c01a4563339083e4c04267b0cd89
4
- data.tar.gz: 134b60d1f35fdb047bf7cd195eb0ca7153d26ec9
3
+ metadata.gz: d495303bb5a7733b5fd5feb751563a505d700db5
4
+ data.tar.gz: 5c8defae79ace760ed398e9d8565ce642dfbe11c
5
5
  SHA512:
6
- metadata.gz: 486543f3afa4f34f92263547babf2a20245e285e88bc8c013827c660ae43d2ab9be645c6342767b66e86d5d1dc4ef7cf12cd0cf795ce71dd18c422aed4eb2b4c
7
- data.tar.gz: 14db1b9b171195d51bf0fc5af2954adee390a8f7dcb5eb7115c49802353cc072e8b3a19181b22f9823c39d8018918f62b75059da91479df0d4750a6fc02f9fd1
6
+ metadata.gz: 8fc82355c9e9a62a1f06501be6eedc76231d7a0c9b90f5f3fe21730cd32cfbd476c4e6520901b69a11a5ebca9fb173d158baacf786d0f9455b8b2183e6d188c0
7
+ data.tar.gz: 9909db6de4dd0a69f075eb5ca6e91c345b4d7e5d6f35bdc2fc36d5e0efaa912a3f7aa42b145143c82cd13bb07ffcaf2407923ad13f13c812463c42ad34f7ac24
data/ChangeLog.md CHANGED
@@ -1,3 +1,9 @@
1
+ ### 0.1.7 / 2016-08-01:
2
+
3
+ * Fix test specs
4
+ * Fix miscount when interval too high
5
+ * Expand model and object tests
6
+
1
7
  ### 0.1.6 / 2016-08-01:
2
8
 
3
9
  * Add test specs
@@ -16,19 +16,17 @@ module RedisThrottler
16
16
  subject = opts[:by] || :id
17
17
  limit = opts[:limit] || 5
18
18
  threshold = opts[:for] || 900
19
- interval = opts[:interval] || 5
20
-
21
- bucket_span = [interval, 600].max
19
+ interval = opts[:interval] || ([threshold,120].max)/120
20
+ bucket_span = threshold * 2
22
21
 
23
22
  throttler = RedisThrottler::Base.new("#{klass}:#{key}", bucket_interval: interval, bucket_span: bucket_span)
24
- @limits[key] = "#{subject.to_s} limit #{limit} per #{threshold} sec"
23
+ @limits[key] = { :limit => limit, :threshold => threshold }
25
24
 
26
- # includes('?') will return true
27
25
  method = "#{key}_throttler"
28
26
 
29
27
  %w(limits limits?).each do |string|
30
28
  define_singleton_method(string) { string.include?('?') || @limits }
31
- define_method(string) { string.include?('?') || self.class.instance_variable_get('@limits')}
29
+ define_method(string) { string.include?('?') || self.class.instance_variable_get(:@limits)}
32
30
  end
33
31
 
34
32
  # i used Procs because they don't complain about arity
@@ -49,7 +47,6 @@ module RedisThrottler
49
47
  define_singleton_method("#{key}_#{magic.to_s}") { |id, within = threshold| eval meth.call(id, within) }
50
48
  define_method("#{key}_#{magic.to_s}") { |within = threshold| eval meth.call("#{self.send subject}", within) }
51
49
  end
52
-
53
50
  end
54
51
  end
55
52
  end
@@ -1,3 +1,3 @@
1
1
  module RedisThrottler
2
- VERSION = '0.1.6'
2
+ VERSION = '0.1.7'
3
3
  end
data/spec/model_spec.rb CHANGED
@@ -2,29 +2,37 @@ require 'spec_helper'
2
2
 
3
3
  describe TestClass do
4
4
 
5
- it 'should be able to define throttle' do
6
- expect(TestClass).to respond_to :throttle
5
+ # we will test the firstly defined throttle
6
+ before do
7
+ throttle = TestClass.instance_variable_get(:@limits)
8
+ key = throttle.keys[0]
9
+ @count_to_fail = throttle[key][:limit]
10
+ @time_til_okay = throttle[key][:threshold]
7
11
  end
8
12
 
9
- it 'should have a throttler for defined throttle' do
10
- expect(TestClass.logins_throttler.class).to eq(RedisThrottler::Base)
13
+ it 'Klass.throttle' do
14
+ expect(TestClass).to respond_to :throttle
11
15
  end
12
16
 
13
- it 'should display limits as hash' do
17
+ it '.limits' do
14
18
  expect(TestClass.limits).to be_a(Hash)
15
19
  end
16
20
 
17
- it 'should respond to limits? correctly' do
21
+ it '.limits?' do
18
22
  expect(TestClass.limits?).to eq(true)
19
23
  end
20
24
 
21
- it 'should be able to increment throttler by subject' do
25
+ it '.#{key}_throttler' do
26
+ expect(TestClass.logins_throttler.class).to eq(RedisThrottler::Base)
27
+ end
28
+
29
+ it '.#{key}_increments(id)' do
22
30
  TestClass.logins_increment('testid')
23
31
  TestClass.logins_increment('testid')
24
32
  expect(TestClass.logins_count('testid')).to eq(2)
25
33
  end
26
34
 
27
- it 'should responsd to exceeded? correctly' do
35
+ it '.#{key}_exceeded?(id)' do
28
36
  TestClass.logins_throttler.add('testid', 10)
29
37
  expect(TestClass.logins_exceeded?('testid')).to eq(true)
30
38
 
@@ -32,17 +40,18 @@ describe TestClass do
32
40
  expect(TestClass.logins_exceeded?('testid2')).to eq(false)
33
41
  end
34
42
 
35
- it 'should not be rate-limited after interval' do
43
+ it 'counts right' do
44
+ @count_to_fail.times { TestClass.logins_increment('test4') }
45
+ expect(TestClass.logins_count('test4')).to eq(TestClass.logins_throttler.count('test4', 60))
46
+ end
47
+
48
+ it 'recovers after limit passed' do
36
49
  expect(TestClass.logins_exceeded?('test3')).to eq(false)
37
- 10.times { TestClass.logins_increment('test3') }
50
+ @count_to_fail.times { TestClass.logins_increment('test3') }
51
+
38
52
  expect(TestClass.logins_exceeded?('test3')).to eq(true)
39
- Timecop.travel(60) do
53
+ Timecop.travel(@time_til_okay) do
40
54
  expect(TestClass.logins_exceeded?('test3')).to eq(false)
41
55
  end
42
56
  end
43
-
44
- it 'should return counter value for subject within defined limits' do
45
- 10.times { TestClass.logins_increment('test4') }
46
- expect(TestClass.logins_count('test4')).to eq(TestClass.logins_throttler.count('test4', 60))
47
- end
48
57
  end
data/spec/object_spec.rb CHANGED
@@ -3,40 +3,64 @@ require 'spec_helper'
3
3
  describe 'Instace of TestClass' do
4
4
  before do
5
5
  @test = TestClass.new
6
+ throttle = TestClass.instance_variable_get(:@limits)
7
+ key = throttle.keys[0]
8
+ @count_to_fail = throttle[key][:limit]
9
+ @time_til_okay = throttle[key][:threshold]
6
10
  end
7
11
 
8
- it 'should have a throttler for defined throttle' do
9
- expect(@test.logins_throttler.class).to eq(RedisThrottler::Base)
12
+ it 'includes RedisThrottler' do
13
+ expect(@test).to be_a_kind_of(RedisThrottler)
10
14
  end
11
15
 
12
- it 'should display limits as hash' do
16
+ it '.limits' do
13
17
  expect(@test.limits).to be_a(Hash)
14
18
  end
15
19
 
16
- it 'should respond to limits? correctly' do
20
+ it '.limits?' do
17
21
  expect(@test.limits?).to eq(true)
18
22
  end
19
23
 
20
- it 'should be able to increment throttler by subject' do
24
+ it '.#{key}_throttler' do
25
+ expect(@test.logins_throttler.class).to eq(RedisThrottler::Base)
26
+ end
27
+
28
+ it '.#{key}_increment' do
21
29
  @test.logins_increment
22
30
  @test.logins_increment
23
31
  expect(@test.logins_count).to eq(2)
24
32
  end
25
33
 
26
- it 'should responsd to exceeded? correctly' do
27
- 10.times do
34
+ it '.#{key}_exceeded?' do
35
+ @count_to_fail.times do
28
36
  @test.logins_increment
29
37
  end
30
38
  expect(@test.logins_exceeded?).to eq(true)
31
39
  end
32
40
 
33
- it 'should not be rate-limited after interval' do
34
- Timecop.travel(60) do
41
+ it 'counts right' do
42
+ expect(@test.logins_count).to eq(TestClass.logins_count(@test.id))
43
+
44
+ 4.times { @test.logins_increment }
45
+
46
+ Timecop.travel(@time_til_okay) do
47
+ (@count_to_fail - 1).times do
48
+ @test.logins_increment
49
+ end
50
+
51
+ expect(@test.logins_count(1)).to eq(@count_to_fail - 1)
35
52
  expect(@test.logins_exceeded?).to eq(false)
36
53
  end
37
54
  end
38
55
 
39
- it 'should return counter value for subject within defined limits' do
40
- expect(@test.logins_count).to eq(TestClass.logins_count(@test.id))
56
+
57
+ it 'recovers after limit passed' do
58
+ @count_to_fail.times do
59
+ @test.logins_increment
60
+ end
61
+ expect(@test.logins_exceeded?).to eq(true)
62
+ Timecop.travel(@time_til_okay) do
63
+ expect(@test.logins_exceeded?).to eq(false)
64
+ end
41
65
  end
42
66
  end
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ require 'timecop'
5
5
 
6
6
  class TestClass
7
7
  include RedisThrottler
8
- throttle :logins, limit: 10, for: 60
8
+ throttle :logins, limit: 10, for: 5000
9
9
 
10
10
  def initialize
11
11
  @id = 1234
@@ -15,3 +15,5 @@ class TestClass
15
15
  @id
16
16
  end
17
17
  end
18
+
19
+ @test = TestClass.new
@@ -7,23 +7,23 @@ describe RedisThrottler::Base do
7
7
  @rl.send(:redis).flushdb
8
8
  end
9
9
 
10
- it 'should set_bucket_expiry to the bucket_span if not defined' do
10
+ it 'sets set_bucket_expiry to the bucket_span if not defined' do
11
11
  expect(@rl.instance_variable_get(:@bucket_span)).to eq(@rl.instance_variable_get(:@bucket_expiry))
12
12
  end
13
13
 
14
- it 'should not allow bucket count less than 3' do
14
+ it 'does not allow bucket count less than 3' do
15
15
  expect do
16
16
  RedisThrottler::Base.new('test', {:bucket_span => 1, :bucket_interval => 1})
17
17
  end.to raise_error(ArgumentError)
18
18
  end
19
19
 
20
- it 'should not allow bucket expiry to be larger than the bucket span' do
20
+ it 'does not allow bucket_expiry > bucket_span' do
21
21
  expect do
22
22
  RedisThrottler::Base.new("key", {:bucket_expiry => 1200})
23
23
  end.to raise_error(ArgumentError)
24
24
  end
25
25
 
26
- it 'should be able to add to the count for a given subject' do
26
+ it '.add(\'string\', 1)' do
27
27
  @rl.add('value1')
28
28
  @rl.add('value1')
29
29
  expect(@rl.count('value1', 1)).to eq(2)
@@ -33,12 +33,12 @@ describe RedisThrottler::Base do
33
33
  end
34
34
  end
35
35
 
36
- it 'should be able to add to the count by more than 1' do
36
+ it '.add(\'string\', 3)' do
37
37
  @rl.add('value1', 3)
38
38
  expect(@rl.count('value1', 1)).to eq(3)
39
39
  end
40
40
 
41
- it 'should be able to add to the count for a non-string subject' do
41
+ it '.add(123, 1)' do
42
42
  @rl.add(123)
43
43
  @rl.add(123)
44
44
  expect(@rl.count(123, 1)).to eq(2)
@@ -48,12 +48,12 @@ describe RedisThrottler::Base do
48
48
  end
49
49
  end
50
50
 
51
- it 'should return counter value' do
51
+ it '.count' do
52
52
  counter_value = @rl.add("value1")
53
53
  expect(@rl.count("value1", 1)).to eq(counter_value)
54
54
  end
55
55
 
56
- it 'respond to exceeded? method correctly' do
56
+ it '.exceeded?' do
57
57
  5.times do
58
58
  @rl.add("value1")
59
59
  end
@@ -69,7 +69,7 @@ describe RedisThrottler::Base do
69
69
  expect(@rl.within_bounds?("value1", {:threshold => 10, :interval => 30})).to be false
70
70
  end
71
71
 
72
- it "accept a threshold and a block that gets executed once it's below the threshold" do
72
+ it 'accepts a threshold and a block that gets executed once it\'s below the threshold' do
73
73
  expect(@rl.count("key", 30)).to eq(0)
74
74
  31.times do
75
75
  @rl.add("key")
@@ -93,7 +93,7 @@ describe RedisThrottler::Base do
93
93
  expect(@value).to be 1
94
94
  end
95
95
 
96
- it 'counts correclty if bucket_span equals count-interval ' do
96
+ it 'counts correctly when bucket_span equals count-interval ' do
97
97
  @rl = RedisThrottler::Base.new('key', {:bucket_span => 10, bucket_interval: 1})
98
98
  @rl.add('value1')
99
99
  expect(@rl.count('value1', 10)).to eql(1)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-throttler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Surdam