redis-throttle 0.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.adoc +178 -0
- data/lib/redis/throttle.rb +17 -7
- data/lib/redis-throttle.rb +4 -0
- data/lib/redis_throttle/api.lua +195 -0
- data/lib/redis_throttle/api.rb +118 -0
- data/lib/redis_throttle/class_methods.rb +43 -0
- data/lib/redis_throttle/concurrency.rb +75 -0
- data/lib/redis_throttle/rate_limit.rb +73 -0
- data/lib/redis_throttle/version.rb +6 -0
- data/lib/redis_throttle.rb +286 -0
- metadata +33 -32
- data/CHANGES.md +0 -7
- data/README.md +0 -123
- data/lib/redis/throttle/concurrency.lua +0 -13
- data/lib/redis/throttle/concurrency.rb +0 -43
- data/lib/redis/throttle/errors.rb +0 -8
- data/lib/redis/throttle/script.rb +0 -50
- data/lib/redis/throttle/threshold.lua +0 -12
- data/lib/redis/throttle/threshold.rb +0 -38
- data/lib/redis/throttle/version.rb +0 -8
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "digest"
|
4
|
-
require "redis/errors"
|
5
|
-
|
6
|
-
require_relative "./errors"
|
7
|
-
|
8
|
-
class Redis
|
9
|
-
module Throttle
|
10
|
-
# Simple helper to run script by it's sha1 digest with fallbak to script
|
11
|
-
# load if it was not loaded yet.
|
12
|
-
class Script
|
13
|
-
# Redis error fired when script ID is unkown.
|
14
|
-
NOSCRIPT = "NOSCRIPT"
|
15
|
-
private_constant :NOSCRIPT
|
16
|
-
|
17
|
-
LUA_ERROR_MESSAGE = %r{
|
18
|
-
ERR\s
|
19
|
-
(?<message>Error\s(?:compiling|running)\sscript\s\(.*?\)):\s
|
20
|
-
(?:[^:]+:\d+:\s)+
|
21
|
-
(?<details>.+)
|
22
|
-
}x.freeze
|
23
|
-
private_constant :LUA_ERROR_MESSAGE
|
24
|
-
|
25
|
-
def initialize(source)
|
26
|
-
@source = -source.to_s
|
27
|
-
@digest = Digest::SHA1.hexdigest(@source)
|
28
|
-
end
|
29
|
-
|
30
|
-
def call(redis, keys: [], argv: [])
|
31
|
-
__call__(redis, :keys => keys, :argv => argv)
|
32
|
-
rescue Redis::CommandError => e
|
33
|
-
md = LUA_ERROR_MESSAGE.match(e.message.to_s)
|
34
|
-
raise unless md
|
35
|
-
|
36
|
-
raise LuaError, [md[:message], md[:details]].compact.join(": ")
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def __call__(redis, keys:, argv:)
|
42
|
-
redis.evalsha(@digest, keys, argv)
|
43
|
-
rescue Redis::CommandError => e
|
44
|
-
raise unless e.message.include?(NOSCRIPT)
|
45
|
-
|
46
|
-
redis.eval(@source, keys, argv)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
local bucket, limit, period, now =
|
2
|
-
KEYS[1], tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3])
|
3
|
-
|
4
|
-
if limit <= redis.call("LLEN", bucket) and now - redis.call("LINDEX", bucket, -1) < period then
|
5
|
-
return 1
|
6
|
-
end
|
7
|
-
|
8
|
-
redis.call("LPUSH", bucket, now)
|
9
|
-
redis.call("LTRIM", bucket, 0, limit - 1)
|
10
|
-
redis.call("EXPIRE", bucket, period)
|
11
|
-
|
12
|
-
return 0
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "./script"
|
4
|
-
|
5
|
-
class Redis
|
6
|
-
module Throttle
|
7
|
-
class Threshold
|
8
|
-
SCRIPT = Script.new(File.read("#{__dir__}/threshold.lua"))
|
9
|
-
private_constant :SCRIPT
|
10
|
-
|
11
|
-
NOOP = ->(_) { nil }
|
12
|
-
private_constant :NOOP
|
13
|
-
|
14
|
-
# @param bucket [#to_s]
|
15
|
-
# @param limit [#to_i]
|
16
|
-
# @param period [#to_i]
|
17
|
-
def initialize(bucket, limit:, period:)
|
18
|
-
@bucket = bucket.to_s
|
19
|
-
@limit = limit.to_i
|
20
|
-
@period = period.to_i
|
21
|
-
end
|
22
|
-
|
23
|
-
# @param redis [Redis, Redis::Namespace]
|
24
|
-
# @return [Boolean]
|
25
|
-
def acquire(redis)
|
26
|
-
SCRIPT
|
27
|
-
.call(redis, :keys => [@bucket], :argv => [@limit, @period, Time.now.to_i])
|
28
|
-
.zero?
|
29
|
-
end
|
30
|
-
|
31
|
-
# @param redis [Redis, Redis::Namespace]
|
32
|
-
# @return [void]
|
33
|
-
def reset(redis)
|
34
|
-
redis.del(@bucket)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|