prorate 0.7.0 → 0.7.1

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
  SHA256:
3
- metadata.gz: bb2c78403fd3d37fd073ccf736618673e532c6fc53efd7e1c342c7edebc4037f
4
- data.tar.gz: 497b74b1d07d1590e44f338f7150b6b75fe5ed154af82d052381915a2b174c69
3
+ metadata.gz: 7e00071a8bb75be7ca3c74ecaf662e049f5c55cae7cb867c9851062efd5b8073
4
+ data.tar.gz: 277671f9b2dcce7d032e9f9f38b294ced2ca953cd0f85b940d488f3ff306ee38
5
5
  SHA512:
6
- metadata.gz: d2a262971d745073dfd385088d92bf40667fa8108e6c3b71982b17fad41d6ee94472e40f8189badfa6131ac853a0dfe381e9bfbef93a0b7bbd24c3f39339251f
7
- data.tar.gz: 33f4f60558e7cee9fd671ebe48f4e35fc67e58c2ea5ad5cde5e40368b8b486e941eabb71ddf3dfaa87a9380689d31c059d56ea81cfa8860a955409d075840824
6
+ metadata.gz: 40e22d2cdb70cb407b7cc2135624a373e95e83514cfa8bb2f42a6106b40640b458a017212967fb533ba080e3e4707199a1fb1e2414b68f1289e1d24b15b05fbc
7
+ data.tar.gz: 269d8ef7d384c08c928d3bed3412b2e7ae470e696ff03042744c79bd696962a9a7a82d099de8a153aef344029f40e8640d4e772bee90054b64b4f0183c96d2c9
@@ -1,3 +1,9 @@
1
+ # 0.7.1
2
+
3
+ * Fix use of a ConnectionPool as `redis:` argument which was broken in 0.7.0
4
+ * Use the Lua KEYS argument in `rate_limit.lua` for future-proof clustering support
5
+ instead of computing the touched keys inside the Lua script.
6
+
1
7
  # 0.7.0
2
8
 
3
9
  * Add a naked `LeakyBucket` object which allows one to build sophisticated rate limiting relying
data/Rakefile CHANGED
@@ -9,6 +9,10 @@ YARD::Rake::YardocTask.new(:doc) do |t|
9
9
  t.files = ['lib/**/*.rb', '-', 'LICENSE.txt', 'CHANGELOG.md']
10
10
  end
11
11
 
12
- RSpec::Core::RakeTask.new(:spec)
12
+ RSpec::Core::RakeTask.new(:spec) do |spec|
13
+ spec.rspec_opts = ["-c", "--order=rand"]
14
+ spec.pattern = FileList['spec/**/*_spec.rb']
15
+ end
16
+
13
17
  RuboCop::RakeTask.new(:rubocop)
14
18
  task default: [:spec, :rubocop]
@@ -60,7 +60,7 @@ module Prorate
60
60
  # If your bucket is specific to a user, a browser or an IP address you need to mix in
61
61
  # those values into the key prefix as appropriate.
62
62
  # @param leak_rate[Float] the leak rate of the bucket, in tokens per second
63
- # @param redis[Redis,#with] a Redis connection or a ConnectonPool instance
63
+ # @param redis[Redis,#with] a Redis connection or a ConnectionPool instance
64
64
  # if you are using the connection_pool gem. With a connection pool Prorate will
65
65
  # checkout a connection using `#with` and check it in when it's done.
66
66
  # @param bucket_capacity[Numeric] how many tokens is the bucket capped at.
@@ -70,7 +70,7 @@ module Prorate
70
70
  # of 12, and will then immediately start leaking again.
71
71
  def initialize(redis_key_prefix:, leak_rate:, redis:, bucket_capacity:)
72
72
  @redis_key_prefix = redis_key_prefix
73
- @redis = NullPool.new(redis) unless redis.respond_to?(:with)
73
+ @redis = redis.respond_to?(:with) ? redis : NullPool.new(redis)
74
74
  @leak_rate = leak_rate.to_f
75
75
  @capacity = bucket_capacity.to_f
76
76
  end
@@ -8,13 +8,21 @@
8
8
  redis.replicate_commands()
9
9
  -- make some nicer looking variable names:
10
10
  local retval = nil
11
- local bucket_level_key = ARGV[1] .. ".bucket_level"
12
- local last_updated_key = ARGV[1] .. ".last_updated"
13
- local block_key = ARGV[1] .. ".block"
14
- local max_bucket_capacity = tonumber(ARGV[2])
15
- local leak_rate = tonumber(ARGV[3])
16
- local block_duration = tonumber(ARGV[4])
17
- local n_tokens = tonumber(ARGV[5]) -- How many tokens this call adds to the bucket. Defaults to 1
11
+
12
+ -- Redis documentation recommends passing the keys separately so that Redis
13
+ -- can - in the future - verify that they live on the same shard of a cluster, and
14
+ -- raise an error if they are not. As far as can be understood this functionality is not
15
+ -- yet present, but if we can make a little effort to make ourselves more future proof
16
+ -- we should.
17
+ local bucket_level_key = KEYS[1]
18
+ local last_updated_key = KEYS[2]
19
+ local block_key = KEYS[3]
20
+
21
+ -- and the config variables
22
+ local max_bucket_capacity = tonumber(ARGV[1])
23
+ local leak_rate = tonumber(ARGV[2])
24
+ local block_duration = tonumber(ARGV[3])
25
+ local n_tokens = tonumber(ARGV[4]) -- How many tokens this call adds to the bucket. Defaults to 1
18
26
 
19
27
  -- Take the Redis timestamp
20
28
  local redis_time = redis.call("TIME") -- Array of [seconds, microseconds]
@@ -13,7 +13,7 @@ module Prorate
13
13
  def initialize(name:, limit:, period:, block_for:, redis:, logger: Prorate::NullLogger)
14
14
  @name = name.to_s
15
15
  @discriminators = [name.to_s]
16
- @redis = NullPool.new(redis) unless redis.respond_to?(:with)
16
+ @redis = redis.respond_to?(:with) ? redis : NullPool.new(redis)
17
17
  @logger = logger
18
18
  @block_for = block_for
19
19
 
@@ -135,9 +135,15 @@ module Prorate
135
135
  end
136
136
 
137
137
  def run_lua_throttler(identifier:, bucket_capacity:, leak_rate:, block_for:, n_tokens:)
138
+ # Computing the identifier is somewhat involved so we should avoid doing it too often
139
+ id = identifier
140
+ bucket_level_key = "#{id}.bucket_level"
141
+ last_updated_key = "#{id}.last_updated"
142
+ block_key = "#{id}.block"
143
+
138
144
  @redis.with do |redis|
139
145
  begin
140
- redis.evalsha(LUA_SCRIPT_HASH, [], [identifier, bucket_capacity, leak_rate, block_for, n_tokens])
146
+ redis.evalsha(LUA_SCRIPT_HASH, keys: [bucket_level_key, last_updated_key, block_key], argv: [bucket_capacity, leak_rate, block_for, n_tokens])
141
147
  rescue Redis::CommandError => e
142
148
  if e.message.include? "NOSCRIPT"
143
149
  # The Redis server has never seen this script before. Needs to run only once in the entire lifetime
@@ -1,3 +1,3 @@
1
1
  module Prorate
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prorate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-17 00:00:00.000000000 Z
11
+ date: 2020-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -173,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
173
  - !ruby/object:Gem::Version
174
174
  version: '0'
175
175
  requirements: []
176
- rubygems_version: 3.0.3
176
+ rubygems_version: 3.0.6
177
177
  signing_key:
178
178
  specification_version: 4
179
179
  summary: Time-restricted rate limiter using Redis