prop 1.0.1 → 1.0.2
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 +7 -0
- data/.travis.yml +1 -0
- data/lib/prop.rb +2 -2
- data/lib/prop/limiter.rb +26 -10
- data/prop.gemspec +2 -2
- data/test/helper.rb +0 -2
- data/test/test_limiter.rb +107 -63
- metadata +14 -24
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6876580ba3b335c884fbf9f549931b1a200f8be
|
4
|
+
data.tar.gz: 062fa3bf0d3f237e09ad258a1257559581bdfcf5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75bf0a8a9c115a60e1ffaafa00aaf14c28837174a4a6efbb84183838963bc022c53dc5625bdfdb9ea71145b63a4edfd3127d6684744e5ad993c3b4d09d9231b2
|
7
|
+
data.tar.gz: ed67700ce432878bd7790145779f309d6a7b82192421cd5bbefe99133f6d99e3f385a5ec7a17360e79de8a05835cc60c5cda3bc0dacf0e5b8b15f47234ac7ebd
|
data/lib/prop.rb
CHANGED
@@ -2,12 +2,12 @@ require "prop/limiter"
|
|
2
2
|
require "forwardable"
|
3
3
|
|
4
4
|
module Prop
|
5
|
-
VERSION = "0.
|
5
|
+
VERSION = "1.0.2"
|
6
6
|
|
7
7
|
# Short hand for accessing Prop::Limiter methods
|
8
8
|
class << self
|
9
9
|
extend Forwardable
|
10
10
|
def_delegators :"Prop::Limiter", :read, :write, :configure, :disabled, :before_throttle
|
11
|
-
def_delegators :"Prop::Limiter", :throttle!, :throttled?, :count, :query, :reset
|
11
|
+
def_delegators :"Prop::Limiter", :throttle, :throttle!, :throttled?, :count, :query, :reset
|
12
12
|
end
|
13
13
|
end
|
data/lib/prop/limiter.rb
CHANGED
@@ -49,11 +49,10 @@ module Prop
|
|
49
49
|
# handle - the registered handle associated with the action
|
50
50
|
# key - a custom request specific key, e.g. [ account.id, "download", request.remote_ip ]
|
51
51
|
# options - request specific overrides to the defaults configured for this handle
|
52
|
-
#
|
52
|
+
# (optional) a block of code that this throttle is guarding
|
53
53
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
def throttle!(handle, key = nil, options = {}, &blk)
|
54
|
+
# Returns true if the threshold for this handle has been reached, else returns false
|
55
|
+
def throttle(handle, key = nil, options = {})
|
57
56
|
options, cache_key = prepare(handle, key, options)
|
58
57
|
counter = reader.call(cache_key).to_i
|
59
58
|
|
@@ -63,18 +62,35 @@ module Prop
|
|
63
62
|
before_throttle_callback.call(handle, key, options[:threshold], options[:interval])
|
64
63
|
end
|
65
64
|
|
66
|
-
|
65
|
+
true
|
67
66
|
else
|
68
67
|
increment = options.key?(:increment) ? options[:increment].to_i : 1
|
69
|
-
|
68
|
+
writer.call(cache_key, counter + increment)
|
69
|
+
|
70
|
+
yield if block_given?
|
71
|
+
|
72
|
+
false
|
70
73
|
end
|
71
74
|
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Public: Records a single action for the given handle/key combination.
|
78
|
+
#
|
79
|
+
# handle - the registered handle associated with the action
|
80
|
+
# key - a custom request specific key, e.g. [ account.id, "download", request.remote_ip ]
|
81
|
+
# options - request specific overrides to the defaults configured for this handle
|
82
|
+
# (optional) a block of code that this throttle is guarding
|
83
|
+
#
|
84
|
+
# Raises Prop::RateLimited if the number if the threshold for this handle has been reached
|
85
|
+
# Returns the value of the block if given a such, otherwise the current count of the throttle
|
86
|
+
def throttle!(handle, key = nil, options = {})
|
87
|
+
options, cache_key = prepare(handle, key, options)
|
72
88
|
|
73
|
-
if
|
74
|
-
|
75
|
-
else
|
76
|
-
counter
|
89
|
+
if throttle(handle, key, options)
|
90
|
+
raise Prop::RateLimited.new(options.merge(:cache_key => cache_key, :handle => handle))
|
77
91
|
end
|
92
|
+
|
93
|
+
block_given? ? yield : reader.call(cache_key).to_i
|
78
94
|
end
|
79
95
|
|
80
96
|
# Public: Allows to query whether the given handle/key combination is currently throttled
|
data/prop.gemspec
CHANGED
data/test/helper.rb
CHANGED
data/test/test_limiter.rb
CHANGED
@@ -11,98 +11,142 @@ describe Prop::Limiter do
|
|
11
11
|
|
12
12
|
@start = Time.now
|
13
13
|
Time.stubs(:now).returns(@start)
|
14
|
+
|
15
|
+
Prop.reset(:something)
|
14
16
|
end
|
15
17
|
|
16
|
-
describe "#throttle
|
17
|
-
|
18
|
-
Prop.
|
18
|
+
describe "#throttle" do
|
19
|
+
describe "when disabled" do
|
20
|
+
before { Prop::Limiter.stubs(:disabled?).returns(true) }
|
21
|
+
|
22
|
+
it "returns nil" do
|
23
|
+
assert_nil Prop.throttle(:something)
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
|
-
describe "when disabled" do
|
22
|
-
before { Prop::Limiter.
|
27
|
+
describe "when not disabled" do
|
28
|
+
before { Prop::Limiter.stubs(:disabled?).returns(false) }
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
before { Prop::Limiter.stubs(:at_threshold?).returns(threshold_reached) }
|
30
|
+
describe "and the threshold has been reached" do
|
31
|
+
before { Prop::Limiter.stubs(:at_threshold?).returns(true) }
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
it "returns true" do
|
34
|
+
assert Prop.throttle(:something)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "does not increment the throttle count" do
|
38
|
+
Prop.throttle(:something)
|
39
|
+
|
40
|
+
assert_equal 0, Prop.count(:something)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "when given a block" do
|
44
|
+
before { @test_block_executed = false }
|
45
|
+
|
46
|
+
it "does not execute the block" do
|
47
|
+
Prop.throttle(:something) { @test_block_executed = true }
|
48
|
+
|
49
|
+
refute @test_block_executed
|
32
50
|
end
|
51
|
+
end
|
33
52
|
|
34
|
-
|
35
|
-
|
36
|
-
|
53
|
+
describe "when a before_throttle callback has been specified" do
|
54
|
+
before do
|
55
|
+
Prop.before_throttle do |handle, key, threshold, interval|
|
56
|
+
@handle = handle
|
57
|
+
@key = key
|
58
|
+
@threshold = threshold
|
59
|
+
@interval = interval
|
37
60
|
end
|
61
|
+
|
62
|
+
Prop.throttle(:something, [:extra])
|
63
|
+
end
|
64
|
+
|
65
|
+
it "invokes callback with expected parameters" do
|
66
|
+
assert_equal @handle, :something
|
67
|
+
assert_equal @key, [:extra]
|
68
|
+
assert_equal @threshold, 10
|
69
|
+
assert_equal @interval, 10
|
38
70
|
end
|
39
71
|
end
|
40
72
|
end
|
41
|
-
end
|
42
73
|
|
43
|
-
|
44
|
-
|
74
|
+
describe "and the threshold has not been reached" do
|
75
|
+
before { Prop::Limiter.stubs(:at_threshold?).returns(false) }
|
45
76
|
|
46
|
-
|
47
|
-
|
77
|
+
it "returns false" do
|
78
|
+
refute Prop.throttle(:something)
|
79
|
+
end
|
48
80
|
|
49
|
-
|
50
|
-
|
51
|
-
assert_raises(Prop::RateLimited) { Prop.throttle!(:something) { "wibble" }}
|
52
|
-
end
|
81
|
+
it "increments the throttle count by one" do
|
82
|
+
Prop.throttle(:something)
|
53
83
|
|
54
|
-
|
55
|
-
|
56
|
-
assert_raises(Prop::RateLimited) { Prop.throttle!(:something, nil, :increment => 0) { "wibble" }}
|
57
|
-
assert_equal value, Prop.count(:something)
|
58
|
-
end
|
84
|
+
assert_equal 1, Prop.count(:something)
|
85
|
+
end
|
59
86
|
|
60
|
-
|
61
|
-
|
62
|
-
Prop.before_throttle do |handle, key, threshold, interval|
|
63
|
-
@handle = handle
|
64
|
-
@key = key
|
65
|
-
@threshold = threshold
|
66
|
-
@interval = interval
|
67
|
-
end
|
68
|
-
end
|
87
|
+
it "increments the throttle count by the specified number when provided" do
|
88
|
+
Prop.throttle(:something, nil, :increment => 5)
|
69
89
|
|
70
|
-
|
71
|
-
assert_raises(Prop::RateLimited) { Prop.throttle!(:something, [:extra]) }
|
72
|
-
assert_equal @handle, :something
|
73
|
-
assert_equal @key, [:extra]
|
74
|
-
assert_equal @threshold, 10
|
75
|
-
assert_equal @interval, 10
|
76
|
-
end
|
77
|
-
end
|
90
|
+
assert_equal 5, Prop.count(:something)
|
78
91
|
end
|
79
92
|
|
80
|
-
describe "
|
81
|
-
|
82
|
-
|
93
|
+
describe "when given a block" do
|
94
|
+
before { @test_block_executed = false }
|
95
|
+
|
96
|
+
it "executes the block" do
|
97
|
+
Prop.throttle(:something) { @test_block_executed = true }
|
98
|
+
|
99
|
+
assert @test_block_executed
|
83
100
|
end
|
84
101
|
end
|
85
102
|
end
|
103
|
+
end
|
104
|
+
end
|
86
105
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
106
|
+
describe "#throttle!" do
|
107
|
+
it "throttles the given handle/key combination" do
|
108
|
+
Prop::Limiter.expects(:throttle).with(
|
109
|
+
:something,
|
110
|
+
:key,
|
111
|
+
{
|
112
|
+
:threshold => 10,
|
113
|
+
:interval => 10,
|
114
|
+
:key => 'key',
|
115
|
+
:options => true
|
116
|
+
}
|
117
|
+
)
|
118
|
+
|
119
|
+
Prop.throttle!(:something, :key, :options => true)
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "when the threshold has been reached" do
|
123
|
+
before { Prop::Limiter.stubs(:throttle).returns(true) }
|
124
|
+
|
125
|
+
it "raises a rate-limited exception" do
|
126
|
+
assert_raises(Prop::RateLimited) { Prop.throttle!(:something) }
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "when given a block" do
|
130
|
+
before { @test_block_executed = false }
|
91
131
|
|
92
|
-
|
93
|
-
|
94
|
-
|
132
|
+
it "does not executes the block" do
|
133
|
+
begin
|
134
|
+
Prop.throttle!(:something) { @test_block_executed = true }
|
135
|
+
rescue Prop::RateLimited
|
136
|
+
refute @test_block_executed
|
95
137
|
end
|
96
138
|
end
|
139
|
+
end
|
140
|
+
end
|
97
141
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
142
|
+
describe "when the threshold has not been reached" do
|
143
|
+
it "returns the counter value" do
|
144
|
+
assert_equal Prop.count(:something) + 1, Prop.throttle!(:something)
|
145
|
+
end
|
102
146
|
|
103
|
-
|
104
|
-
|
105
|
-
|
147
|
+
describe "when given a block" do
|
148
|
+
it "returns the return value of the block" do
|
149
|
+
assert_equal 'block_value', Prop.throttle!(:something) { 'block_value' }
|
106
150
|
end
|
107
151
|
end
|
108
152
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Morten Primdahl
|
@@ -14,65 +13,57 @@ dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: bundler
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: minitest
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: mocha
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
description: Gem for implementing rate limits.
|
@@ -106,27 +97,26 @@ files:
|
|
106
97
|
homepage: http://github.com/zendesk/prop
|
107
98
|
licenses:
|
108
99
|
- Apache License Version 2.0
|
100
|
+
metadata: {}
|
109
101
|
post_install_message:
|
110
102
|
rdoc_options: []
|
111
103
|
require_paths:
|
112
104
|
- lib
|
113
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
106
|
requirements:
|
116
|
-
- -
|
107
|
+
- - '>='
|
117
108
|
- !ruby/object:Gem::Version
|
118
109
|
version: '0'
|
119
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
111
|
requirements:
|
122
|
-
- -
|
112
|
+
- - '>='
|
123
113
|
- !ruby/object:Gem::Version
|
124
114
|
version: '0'
|
125
115
|
requirements: []
|
126
116
|
rubyforge_project: prop
|
127
|
-
rubygems_version:
|
117
|
+
rubygems_version: 2.0.14
|
128
118
|
signing_key:
|
129
|
-
specification_version:
|
119
|
+
specification_version: 4
|
130
120
|
summary: Gem for implementing rate limits.
|
131
121
|
test_files:
|
132
122
|
- test/test_key.rb
|