redis-throttler 0.1.6 → 0.1.7

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 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