prop 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +3 -0
- data/lib/prop.rb +1 -1
- data/lib/prop/interval_strategy.rb +7 -3
- data/lib/prop/leaky_bucket_strategy.rb +3 -2
- data/lib/prop/limiter.rb +2 -3
- data/lib/prop/options.rb +13 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 850a96785d6d002acd243a5edf5cca965bd46bd1
|
4
|
+
data.tar.gz: 9ffb56011562feb0d9cf2c5ab62705420d59d46e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cfee5d2c8af78a8a9273bdc873ba83ee6bb81237ca7cb253fce98dbf6180cff96f1004759e5d2fc4ee8e01364dddfae7f4b94c3909f547b08bcd3b109c9d7d2
|
7
|
+
data.tar.gz: 61e6d22651a9017e827d34220511fd8dd6dc60acaa69908968082d71a0ee6926859c0509f08b12fdf5a4d4310f83b95d0cf7b4137f713323d70fb88defcd0bbc
|
data/README.md
CHANGED
@@ -37,6 +37,9 @@ Example: Limit on accepted emails per hour from a given user, by defining a thre
|
|
37
37
|
|
38
38
|
```ruby
|
39
39
|
Prop.configure(:mails_per_hour, threshold: 100, interval: 1.hour, description: "Mail rate limit exceeded")
|
40
|
+
|
41
|
+
# Block requests by setting threshold to 0
|
42
|
+
Prop.configure(:mails_per_hour, threshold: 0, interval: 1.hour, description: "All mail is blocked")
|
40
43
|
```
|
41
44
|
|
42
45
|
```ruby
|
data/lib/prop.rb
CHANGED
@@ -56,8 +56,8 @@ module Prop
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def validate_options!(options)
|
59
|
-
|
60
|
-
|
59
|
+
validate_threshold(options[:threshold], :threshold)
|
60
|
+
validate_interval(options[:interval], :interval)
|
61
61
|
|
62
62
|
amount = options[:increment] || options[:decrement]
|
63
63
|
if amount
|
@@ -67,7 +67,11 @@ module Prop
|
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
-
def
|
70
|
+
def validate_threshold(option, key)
|
71
|
+
raise ArgumentError.new("#{key.inspect} must be a non-negative Integer") if !option.is_a?(Integer) || option < 0
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_interval(option, key)
|
71
75
|
raise ArgumentError.new("#{key.inspect} must be a positive Integer") if !option.is_a?(Integer) || option <= 0
|
72
76
|
end
|
73
77
|
|
@@ -8,9 +8,10 @@ module Prop
|
|
8
8
|
def counter(cache_key, options)
|
9
9
|
bucket = Prop::Limiter.cache.read(cache_key) || zero_counter
|
10
10
|
now = Time.now.to_i
|
11
|
-
|
11
|
+
leak_rate = (now - bucket.fetch(:last_updated)) / options.fetch(:interval).to_f
|
12
|
+
leak_amount = leak_rate * options.fetch(:threshold)
|
12
13
|
|
13
|
-
bucket[:bucket] = [bucket.fetch(:bucket) - leak_amount, 0].max
|
14
|
+
bucket[:bucket] = [(bucket.fetch(:bucket) - leak_amount).to_i, 0].max
|
14
15
|
bucket[:last_updated] = now
|
15
16
|
bucket
|
16
17
|
end
|
data/lib/prop/limiter.rb
CHANGED
@@ -46,8 +46,7 @@ module Prop
|
|
46
46
|
#
|
47
47
|
# Raises Prop::RateLimited if the number if the threshold for this handle has been reached
|
48
48
|
def configure(handle, defaults)
|
49
|
-
|
50
|
-
raise ArgumentError.new("Invalid interval setting") unless defaults[:interval].to_i > 0
|
49
|
+
Prop::Options.validate_options!(defaults)
|
51
50
|
|
52
51
|
self.handles ||= {}
|
53
52
|
self.handles[handle] = defaults
|
@@ -56,7 +55,7 @@ module Prop
|
|
56
55
|
# Public: Disables Prop for a block of code
|
57
56
|
#
|
58
57
|
# block - a block of code within which Prop will not raise
|
59
|
-
def disabled(&
|
58
|
+
def disabled(&_block)
|
60
59
|
@disabled = true
|
61
60
|
yield
|
62
61
|
ensure
|
data/lib/prop/options.rb
CHANGED
@@ -12,17 +12,24 @@ module Prop
|
|
12
12
|
result = defaults.merge(params)
|
13
13
|
|
14
14
|
result[:key] = Prop::Key.normalize(key)
|
15
|
+
result[:strategy] = get_strategy(result)
|
15
16
|
|
16
|
-
result[:strategy]
|
17
|
+
result[:strategy].validate_options!(result)
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.validate_options!(options)
|
22
|
+
get_strategy(options).validate_options!(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.get_strategy(options)
|
26
|
+
if leaky_bucket.include?(options[:strategy])
|
17
27
|
Prop::LeakyBucketStrategy
|
18
|
-
elsif
|
28
|
+
elsif options[:strategy] == nil
|
19
29
|
Prop::IntervalStrategy
|
20
30
|
else
|
21
|
-
|
31
|
+
options[:strategy] # allowing any new/unknown strategy to be used
|
22
32
|
end
|
23
|
-
|
24
|
-
result[:strategy].validate_options!(result)
|
25
|
-
result
|
26
33
|
end
|
27
34
|
|
28
35
|
def self.leaky_bucket
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Morten Primdahl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
version: '0'
|
117
117
|
requirements: []
|
118
118
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.
|
119
|
+
rubygems_version: 2.6.14.4
|
120
120
|
signing_key:
|
121
121
|
specification_version: 4
|
122
122
|
summary: Gem for implementing rate limits.
|