praroter 1.0.0 → 1.0.1

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
  SHA256:
3
- metadata.gz: a107a6850338e77ecac23ff79c3ec477fbdf6615cb6b58a705e2f575752d2493
4
- data.tar.gz: 595c3f911778b4fd1a8a6dd64da6e8c7b0185db0c3ca6fc34bfc3b6b4926f719
3
+ metadata.gz: a14e168451294700f7c71bed654256c51bcf6742f186f8201f9aebe7a1a6e3e5
4
+ data.tar.gz: 5d1995a758edad1c5f054bf665f101fa85ba00bb34eb729415eaf4a7a5f13c1e
5
5
  SHA512:
6
- metadata.gz: 6bb75c4e204bb148c9f7928689c3bf7c0d5c8fb356820a34a6a0160fd7f97606914ae73b561fa9ec3bdb5d1862028ce778e01e5e8145e5f7d7bd1f9eb1d11f72
7
- data.tar.gz: 99192564d7291ede39f07d5d7ee8c0f8c780c37f3faa45726ab141f8987445d5fa8b6c1eeb346cddb29de5e13e6bd241151d5080e26d3135a8a78a1e2f83a463
6
+ metadata.gz: bb3c8fb96ff6f5fdec4fe33eff582ba3db6be91caf2714e28f6ba3b4fb79dccc7dbece841a82de1c2becf507c65124cea12257bbebf7ef856cd4fdf261cef725
7
+ data.tar.gz: 4b242a9abeccf2844cdeba9a0c939f5846255db810f7cd14bafaf05eafebbf5e70f6b021d83683ca92be3e8205b796721ee1f2017990288c8a181c71e5cddfa8
data/README.md CHANGED
@@ -72,6 +72,7 @@ To capture that exception, add this to the controller:
72
72
 
73
73
  ```ruby
74
74
  rescue_from Praroter::Throttled do |e|
75
+ response.set_header('X-Ratelimit-Cost', e.bucket_state.drained)
75
76
  response.set_header('X-Ratelimit-Level', e.bucket_state.level)
76
77
  response.set_header('X-Ratelimit-Capacity', e.bucket_state.capacity)
77
78
  response.set_header('X-Ratelimit-Retry-After', e.retry_in_seconds)
@@ -140,7 +141,8 @@ def index
140
141
  sleep(2.242)
141
142
  end
142
143
 
143
- rescue_from Praroter::FillyBucket::Throttled do |e|
144
+ rescue_from Praroter::Throttled do |e|
145
+ response.set_header('X-Ratelimit-Cost', e.bucket_state.drained)
144
146
  response.set_header('X-Ratelimit-Level', e.bucket_state.level)
145
147
  response.set_header('X-Ratelimit-Capacity', e.bucket_state.capacity)
146
148
  response.set_header('X-Ratelimit-Retry-After', e.retry_in_seconds)
@@ -159,6 +161,7 @@ def api_ratelimit
159
161
  bucket_state = ratelimit_bucket.drain_block do
160
162
  yield
161
163
  end
164
+ response.set_header('X-Ratelimit-Cost', bucket_state.drained)
162
165
  response.set_header('X-Ratelimit-Level', bucket_state.level)
163
166
  response.set_header('X-Ratelimit-Capacity', bucket_state.capacity)
164
167
  end
@@ -0,0 +1,57 @@
1
+ module Praroter
2
+ module FillyBucket
3
+
4
+ class Bucket
5
+ attr_reader :key, :fill_rate, :capacity
6
+
7
+ def initialize(key, fill_rate, capacity, creator)
8
+ @key = key
9
+ @fill_rate = fill_rate
10
+ @capacity = capacity
11
+ @creator = creator
12
+ end
13
+
14
+ def state
15
+ @creator.run_lua_bucket_script(self, 0)
16
+ end
17
+
18
+ def empty?
19
+ state.empty?
20
+ end
21
+
22
+ def full?
23
+ state.full?
24
+ end
25
+
26
+ def throttle!
27
+ bucket_state = state
28
+ if bucket_state.empty?
29
+ remaining_block_time = ((bucket_state.capacity - bucket_state.level).abs / bucket_state.fill_rate) + 3
30
+ raise Praroter::Throttled.new(bucket_state, remaining_block_time)
31
+ end
32
+ bucket_state
33
+ end
34
+
35
+ def drain(amount)
36
+ raise ArgumentError, "drain amount must be positive" if amount < 0
37
+ @creator.run_lua_bucket_script(self, amount)
38
+ end
39
+
40
+ def drain_block
41
+ work_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
42
+ yield
43
+ work_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
44
+ drain(((work_end - work_start) * 1000).to_i)
45
+ end
46
+
47
+ def level_key
48
+ "filly_bucket.#{key}.bucket_level"
49
+ end
50
+
51
+ def last_updated_key
52
+ "filly_bucket.#{key}.last_updated"
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,15 @@
1
+ module Praroter
2
+ module FillyBucket
3
+
4
+ class BucketState < Struct.new(:level, :capacity, :fill_rate, :drained)
5
+ def empty?
6
+ level <= 0
7
+ end
8
+
9
+ def full?
10
+ level >= capacity
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -1,69 +1,6 @@
1
1
  module Praroter
2
-
3
2
  module FillyBucket
4
3
 
5
- class BucketState < Struct.new(:level, :capacity, :fill_rate)
6
- def empty?
7
- level <= 0
8
- end
9
-
10
- def full?
11
- level >= capacity
12
- end
13
- end
14
-
15
- class Bucket
16
- attr_reader :key, :fill_rate, :capacity
17
-
18
- def initialize(key, fill_rate, capacity, creator)
19
- @key = key
20
- @fill_rate = fill_rate
21
- @capacity = capacity
22
- @creator = creator
23
- end
24
-
25
- def state
26
- @creator.run_lua_bucket_script(self, 0)
27
- end
28
-
29
- def empty?
30
- state.empty?
31
- end
32
-
33
- def full?
34
- state.full?
35
- end
36
-
37
- def throttle!
38
- bucket_state = state
39
- if bucket_state.empty?
40
- remaining_block_time = ((bucket_state.capacity - bucket_state.level).abs / bucket_state.fill_rate) + 3
41
- raise Praroter::Throttled.new(bucket_state, remaining_block_time)
42
- end
43
- bucket_state
44
- end
45
-
46
- def drain(amount)
47
- raise ArgumentError, "drain amount must be positive" if amount < 0
48
- @creator.run_lua_bucket_script(self, amount)
49
- end
50
-
51
- def drain_block
52
- work_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
53
- yield
54
- work_end = Process.clock_gettime(Process::CLOCK_MONOTONIC)
55
- drain(((work_end - work_start) * 1000).to_i)
56
- end
57
-
58
- def level_key
59
- "filly_bucket.#{key}.bucket_level"
60
- end
61
-
62
- def last_updated_key
63
- "filly_bucket.#{key}.last_updated"
64
- end
65
- end
66
-
67
4
  class Creator
68
5
  LUA_SCRIPT_CODE = File.read(File.join(__dir__, "filly_bucket.lua"))
69
6
  LUA_SCRIPT_HASH = Digest::SHA1.hexdigest(LUA_SCRIPT_CODE)
@@ -86,7 +23,7 @@ module Praroter
86
23
  keys: [bucket.level_key, bucket.last_updated_key],
87
24
  argv: [bucket.capacity, bucket.fill_rate, amount]
88
25
  )
89
- BucketState.new(new_bucket_level, bucket_capacity, fill_rate)
26
+ BucketState.new(new_bucket_level, bucket_capacity, fill_rate, amount)
90
27
  rescue Redis::CommandError => e
91
28
  if e.message.include? "NOSCRIPT"
92
29
  # The Redis server has never seen this script before. Needs to run only once in the entire lifetime
@@ -103,5 +40,4 @@ module Praroter
103
40
  end
104
41
 
105
42
  end
106
-
107
43
  end
@@ -1,3 +1,3 @@
1
1
  module Praroter
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: praroter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Grubbe
@@ -176,8 +176,10 @@ files:
176
176
  - bin/setup
177
177
  - docker-compose.yml
178
178
  - lib/praroter.rb
179
- - lib/praroter/filly_bucket.lua
180
- - lib/praroter/filly_bucket.rb
179
+ - lib/praroter/filly_bucket/bucket.rb
180
+ - lib/praroter/filly_bucket/bucket_state.rb
181
+ - lib/praroter/filly_bucket/creator.rb
182
+ - lib/praroter/filly_bucket/filly_bucket.lua
181
183
  - lib/praroter/null_logger.rb
182
184
  - lib/praroter/null_pool.rb
183
185
  - lib/praroter/throttled.rb