redis-throttle 1.1.0 → 2.0.0
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 +4 -4
- data/README.adoc +26 -47
- data/lib/redis-throttle.rb +0 -1
- data/lib/redis_throttle/api.rb +17 -22
- data/lib/redis_throttle/version.rb +1 -1
- data/lib/redis_throttle.rb +101 -73
- metadata +8 -10
- data/lib/redis/throttle.rb +0 -22
- data/lib/redis_throttle/class_methods.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dbef2b5249fc1cd8ff9c199e00b11b98dafa0ec8f0a707e9da8af4c5fa3ed1d
|
4
|
+
data.tar.gz: 2a8ddfd1fe58e6f9a3e63cb219ab42450518f804cce806e7778aaca251563cb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74c91479a17ea0759cb6d9a9bcf78c27d1454339a3dca5678cb90aa28c582ed6f11f5d825ff38401a51e9a039728f3d4494887466674f2c29aae4615b376af41
|
7
|
+
data.tar.gz: 4e299f8ae32084daf1c5941629601ba48d4af09d5cec9504421e05a462e0be1a24131929c56c3913f5edf70b4aa53a3a8a57d0d72d90a494193695d8fffb3db5
|
data/README.adoc
CHANGED
@@ -23,16 +23,16 @@ Or install it yourself as:
|
|
23
23
|
# Allow 1 concurrent calls. If call takes more than 10 seconds, consider it
|
24
24
|
# gone (as if process died, or by any other reason did not called `#release`):
|
25
25
|
concurrency = RedisThrottle.concurrency(:bucket_name,
|
26
|
-
:
|
26
|
+
limit: 1,
|
27
27
|
:ttl => 10
|
28
28
|
)
|
29
29
|
|
30
|
-
concurrency.acquire(:
|
31
|
-
concurrency.acquire(:
|
30
|
+
concurrency.acquire(redis, token: "abc") # => "abc"
|
31
|
+
concurrency.acquire(redis, token: "xyz") # => nil
|
32
32
|
|
33
|
-
concurrency.release(:
|
33
|
+
concurrency.release(redis, token: "abc")
|
34
34
|
|
35
|
-
concurrency.acquire(:
|
35
|
+
concurrency.acquire(redis, token: "xyz") # => "xyz"
|
36
36
|
----
|
37
37
|
|
38
38
|
=== Rate Limit
|
@@ -42,15 +42,15 @@ concurrency.acquire(:token => "xyz") # => "xyz"
|
|
42
42
|
# Allow 1 calls per 10 seconds:
|
43
43
|
rate_limit = RedisThrottle.rate_limit(:bucket_name,
|
44
44
|
:limit => 1,
|
45
|
-
:
|
45
|
+
period: 10
|
46
46
|
)
|
47
47
|
|
48
|
-
rate_limit.acquire # => "6a6c6546-268d-4216-bcf3-3139b8e11609"
|
49
|
-
rate_limit.acquire # => nil
|
48
|
+
rate_limit.acquire(redis) # => "6a6c6546-268d-4216-bcf3-3139b8e11609"
|
49
|
+
rate_limit.acquire(redis) # => nil
|
50
50
|
|
51
51
|
sleep 10
|
52
52
|
|
53
|
-
rate_limit.acquire # => "e2926a90-2cf4-4bff-9401-65f3a70d32bd"
|
53
|
+
rate_limit.acquire(redis) # => "e2926a90-2cf4-4bff-9401-65f3a70d32bd"
|
54
54
|
----
|
55
55
|
|
56
56
|
|
@@ -59,11 +59,11 @@ rate_limit.acquire # => "e2926a90-2cf4-4bff-9401-65f3a70d32bd"
|
|
59
59
|
[source,ruby]
|
60
60
|
----
|
61
61
|
throttle = RedisThrottle
|
62
|
-
.concurrency(:db, :
|
63
|
-
.rate_limit(:api_minutely, :
|
64
|
-
.rate_limit(:api_hourly, :
|
62
|
+
.concurrency(:db, limit: 3, ttl: 900)
|
63
|
+
.rate_limit(:api_minutely, limit: 1, period: 60)
|
64
|
+
.rate_limit(:api_hourly, limit: 10, period: 3600)
|
65
65
|
|
66
|
-
throttle.call(:
|
66
|
+
throttle.call(redis, token: "abc") do
|
67
67
|
# do something if all strategies are resolved
|
68
68
|
end
|
69
69
|
----
|
@@ -72,46 +72,17 @@ You can also compose multiple throttlers together:
|
|
72
72
|
|
73
73
|
[source,ruby]
|
74
74
|
----
|
75
|
-
db_limiter = RedisThrottle.concurrency(:db, :
|
75
|
+
db_limiter = RedisThrottle.concurrency(:db, limit: 3, ttl: 900)
|
76
76
|
api_limiter = RedisThrottle
|
77
|
-
.rate_limit(:api_minutely, :
|
78
|
-
.rate_limit(:api_hourly, :
|
77
|
+
.rate_limit(:api_minutely, limit: 1, period: 60)
|
78
|
+
.rate_limit(:api_hourly, limit: 10, period: 3600)
|
79
79
|
|
80
|
-
(db_limiter + api_limiter).call do
|
80
|
+
(db_limiter + api_limiter).call(redis) do
|
81
81
|
# ...
|
82
82
|
end
|
83
83
|
----
|
84
84
|
|
85
85
|
|
86
|
-
=== With ConnectionPool
|
87
|
-
|
88
|
-
If you're using [connection_pool](https://github.com/mperham/connection_pool),
|
89
|
-
you can pass its `#with` method as connection builder:
|
90
|
-
|
91
|
-
[source,ruby]
|
92
|
-
----
|
93
|
-
pool = ConnectionPool.new { Redis.new }
|
94
|
-
throttle = RedisThrottle.new(:redis => pool.method(:with))
|
95
|
-
----
|
96
|
-
|
97
|
-
=== With Sidekiq
|
98
|
-
|
99
|
-
[Sidekiq](https://github.com/mperham/sidekiq): uses ConnectionPool, so you can
|
100
|
-
use the same approach:
|
101
|
-
|
102
|
-
[source,ruby]
|
103
|
-
----
|
104
|
-
throttle = RedisThrottle.new(:redis => Sidekiq.redis_pool.method(:with))
|
105
|
-
----
|
106
|
-
|
107
|
-
Or, you can use its `.redis` method directly:
|
108
|
-
|
109
|
-
[source,ruby]
|
110
|
-
----
|
111
|
-
throttle = RedisThrottle.new(:redis => Sidekiq.method(:redis))
|
112
|
-
----
|
113
|
-
|
114
|
-
|
115
86
|
== Compatibility
|
116
87
|
|
117
88
|
This library aims to support and is tested against:
|
@@ -132,8 +103,15 @@ This library aims to support and is tested against:
|
|
132
103
|
** 4.4.x
|
133
104
|
** 4.5.x
|
134
105
|
** 4.6.x
|
106
|
+
** 4.7.x
|
107
|
+
** 4.8.x
|
108
|
+
** 5.0.x
|
135
109
|
* https://github.com/resque/redis-namespace[redis-namespace]
|
136
110
|
** 1.10.x
|
111
|
+
* https://github.com/redis-rb/redis-client[redis-client]
|
112
|
+
** 0.12.x
|
113
|
+
** 0.13.x
|
114
|
+
** 0.14.x
|
137
115
|
|
138
116
|
If something doesn't work on one of these versions, it's a bug.
|
139
117
|
|
@@ -148,7 +126,8 @@ patches in a timely fashion. If critical issues for a particular implementation
|
|
148
126
|
exist at the time of a major release, support for that Ruby version may be
|
149
127
|
dropped.
|
150
128
|
|
151
|
-
The same applies to *Redis Server*, *redis-rb*,
|
129
|
+
The same applies to *Redis Server*, *redis-rb*, *redis-namespace*,
|
130
|
+
and *redis-client* support.
|
152
131
|
|
153
132
|
|
154
133
|
== Development
|
data/lib/redis-throttle.rb
CHANGED
data/lib/redis_throttle/api.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "redis-prescription"
|
3
|
+
require "redis_prescription"
|
5
4
|
|
6
5
|
require_relative "./concurrency"
|
7
6
|
require_relative "./rate_limit"
|
@@ -26,14 +25,9 @@ class RedisThrottle
|
|
26
25
|
SCRIPT = RedisPrescription.new(File.read("#{__dir__}/api.lua"))
|
27
26
|
private_constant :SCRIPT
|
28
27
|
|
29
|
-
# @param redis [Redis, Redis::Namespace,
|
30
|
-
def initialize(redis
|
31
|
-
@redis =
|
32
|
-
if redis.respond_to?(:to_proc)
|
33
|
-
redis.to_proc
|
34
|
-
else
|
35
|
-
->(&b) { b.call(redis || Redis.current) }
|
36
|
-
end
|
28
|
+
# @param redis [Redis, Redis::Namespace, RedisClient, RedisClient::Decorator::Client]
|
29
|
+
def initialize(redis)
|
30
|
+
@redis = redis
|
37
31
|
end
|
38
32
|
|
39
33
|
# @param strategies [Enumerable<Concurrency, RateLimit>]
|
@@ -60,12 +54,12 @@ class RedisThrottle
|
|
60
54
|
# @return [Array<Concurrency, RateLimit>]
|
61
55
|
def strategies(match:)
|
62
56
|
results = []
|
57
|
+
block = ->(key) { from_key(key)&.then { |strategy| results << strategy } }
|
63
58
|
|
64
|
-
|
65
|
-
redis.
|
66
|
-
|
67
|
-
|
68
|
-
end
|
59
|
+
if redis_client?
|
60
|
+
@redis.scan("MATCH", "#{NAMESPACE}:*:#{match}:*:*", &block)
|
61
|
+
else
|
62
|
+
@redis.scan_each(match: "#{NAMESPACE}:*:#{match}:*:*", &block)
|
69
63
|
end
|
70
64
|
|
71
65
|
results
|
@@ -77,16 +71,17 @@ class RedisThrottle
|
|
77
71
|
strategies.zip(execute(:INFO, to_params(strategies) << :TS << Time.now.to_i)).to_h
|
78
72
|
end
|
79
73
|
|
80
|
-
# @note Used for specs only.
|
81
|
-
# @return [void]
|
82
|
-
def ping
|
83
|
-
@redis.call(&:ping)
|
84
|
-
end
|
85
|
-
|
86
74
|
private
|
87
75
|
|
76
|
+
def redis_client?
|
77
|
+
return true if defined?(::RedisClient) && @redis.is_a?(::RedisClient)
|
78
|
+
return true if defined?(::RedisClient::Decorator::Client) && @redis.is_a?(::RedisClient::Decorator::Client)
|
79
|
+
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
88
83
|
def execute(command, argv)
|
89
|
-
|
84
|
+
SCRIPT.call(@redis, keys: [NAMESPACE], argv: [command, *argv])
|
90
85
|
end
|
91
86
|
|
92
87
|
def from_key(key)
|
data/lib/redis_throttle.rb
CHANGED
@@ -4,18 +4,46 @@ require "concurrent/set"
|
|
4
4
|
require "securerandom"
|
5
5
|
|
6
6
|
require_relative "./redis_throttle/api"
|
7
|
-
require_relative "./redis_throttle/class_methods"
|
8
7
|
require_relative "./redis_throttle/concurrency"
|
9
8
|
require_relative "./redis_throttle/rate_limit"
|
10
9
|
require_relative "./redis_throttle/version"
|
11
10
|
|
12
11
|
class RedisThrottle
|
13
|
-
|
12
|
+
class << self
|
13
|
+
# Syntax sugar for `RedisThrottle.new.concurrency(...)`.
|
14
|
+
#
|
15
|
+
# @see #concurrency
|
16
|
+
# @param (see #concurrency)
|
17
|
+
# @return (see #concurrency)
|
18
|
+
def concurrency(...)
|
19
|
+
new.concurrency(...)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Syntax sugar for `RedisThrottle.new.rate_limit(...)`.
|
23
|
+
#
|
24
|
+
# @see #rate_limit
|
25
|
+
# @param (see #rate_limit)
|
26
|
+
# @return (see #rate_limit)
|
27
|
+
def rate_limit(...)
|
28
|
+
new.rate_limit(...)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return usage info for all known (in use) strategies.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# RedisThrottle.info(:match => "*_api").each do |strategy, current_value|
|
35
|
+
# # ...
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @param redis (see Api#initialize)
|
39
|
+
# @param match [#to_s]
|
40
|
+
# @return (see Api#info)
|
41
|
+
def info(redis, match: "*")
|
42
|
+
Api.new(redis).then { |api| api.info(strategies: api.strategies(match: match.to_s)) }
|
43
|
+
end
|
44
|
+
end
|
14
45
|
|
15
|
-
|
16
|
-
def initialize(redis: nil)
|
17
|
-
# TODO: fix api cloning/duping
|
18
|
-
@api = Api.new(redis: redis)
|
46
|
+
def initialize
|
19
47
|
@strategies = Concurrent::Set.new
|
20
48
|
end
|
21
49
|
|
@@ -48,15 +76,15 @@ class RedisThrottle
|
|
48
76
|
# throttle = RedisThrottle.new
|
49
77
|
#
|
50
78
|
# # Allow max 2 concurrent execution units
|
51
|
-
# throttle.concurrency(:xxx, :
|
79
|
+
# throttle.concurrency(:xxx, limit: 2, ttl: 10)
|
52
80
|
#
|
53
|
-
# throttle.acquire(:
|
54
|
-
# throttle.acquire(:
|
55
|
-
# throttle.acquire(:
|
81
|
+
# throttle.acquire(redis, token: "a") && :aye || :nay # => :aye
|
82
|
+
# throttle.acquire(redis, token: "b") && :aye || :nay # => :aye
|
83
|
+
# throttle.acquire(redis, token: "c") && :aye || :nay # => :nay
|
56
84
|
#
|
57
|
-
# throttle.release(:
|
85
|
+
# throttle.release(redis, token: "a")
|
58
86
|
#
|
59
|
-
# throttle.acquire(:
|
87
|
+
# throttle.acquire(redis, token: "c") && :aye || :nay # => :aye
|
60
88
|
#
|
61
89
|
#
|
62
90
|
# @param (see Concurrency#initialize)
|
@@ -76,17 +104,17 @@ class RedisThrottle
|
|
76
104
|
# throttle = RedisThrottle.new
|
77
105
|
#
|
78
106
|
# # Allow 2 execution units per 10 seconds
|
79
|
-
# throttle.rate_limit(:xxx, :
|
107
|
+
# throttle.rate_limit(:xxx, limit: 2, period: 10)
|
80
108
|
#
|
81
|
-
# throttle.acquire && :aye || :nay # => :aye
|
109
|
+
# throttle.acquire(redis) && :aye || :nay # => :aye
|
82
110
|
# sleep 5
|
83
111
|
#
|
84
|
-
# throttle.acquire && :aye || :nay # => :aye
|
85
|
-
# throttle.acquire && :aye || :nay # => :nay
|
112
|
+
# throttle.acquire(redis) && :aye || :nay # => :aye
|
113
|
+
# throttle.acquire(redis) && :aye || :nay # => :nay
|
86
114
|
#
|
87
115
|
# sleep 6
|
88
|
-
# throttle.acquire && :aye || :nay # => :aye
|
89
|
-
# throttle.acquire && :aye || :nay # => :nay
|
116
|
+
# throttle.acquire(redis) && :aye || :nay # => :aye
|
117
|
+
# throttle.acquire(redis) && :aye || :nay # => :nay
|
90
118
|
#
|
91
119
|
# @param (see RateLimit#initialize)
|
92
120
|
# @return [Throttle] self
|
@@ -101,11 +129,11 @@ class RedisThrottle
|
|
101
129
|
# Merge in strategies of the `other` throttle.
|
102
130
|
#
|
103
131
|
# @example
|
104
|
-
# a = RedisThrottle.concurrency(:a, :
|
105
|
-
# b = RedisThrottle.rate_limit(:b, :
|
132
|
+
# a = RedisThrottle.concurrency(:a, limit: 1, ttl: 2)
|
133
|
+
# b = RedisThrottle.rate_limit(:b, limit: 3, period: 4)
|
106
134
|
# c = RedisThrottle
|
107
|
-
# .concurrency(:a, :
|
108
|
-
# .rate_limit(:b, :
|
135
|
+
# .concurrency(:a, limit: 1, ttl: 2)
|
136
|
+
# .rate_limit(:b, limit: 3, period: 4)
|
109
137
|
#
|
110
138
|
# a.merge!(b)
|
111
139
|
#
|
@@ -120,17 +148,15 @@ class RedisThrottle
|
|
120
148
|
self
|
121
149
|
end
|
122
150
|
|
123
|
-
|
124
|
-
|
125
|
-
# Non-destructive version of {#merge!}. Returns new {Throttle} instance with
|
126
|
-
# union of `self` and `other` strategies.
|
151
|
+
# Non-destructive version of {#merge!}. Returns new {RedisThrottle} instance
|
152
|
+
# with union of `self` and `other` strategies.
|
127
153
|
#
|
128
154
|
# @example
|
129
|
-
# a = RedisThrottle.concurrency(:a, :
|
130
|
-
# b = RedisThrottle.rate_limit(:b, :
|
155
|
+
# a = RedisThrottle.concurrency(:a, limit: 1, ttl: 2)
|
156
|
+
# b = RedisThrottle.rate_limit(:b, limit: 3, period: 4)
|
131
157
|
# c = RedisThrottle
|
132
|
-
# .concurrency(:a, :
|
133
|
-
# .rate_limit(:b, :
|
158
|
+
# .concurrency(:a, limit: 1, ttl: 2)
|
159
|
+
# .rate_limit(:b, limit: 3, period: 4)
|
134
160
|
#
|
135
161
|
# a.merge(b) == c # => true
|
136
162
|
# a == c # => false
|
@@ -142,9 +168,6 @@ class RedisThrottle
|
|
142
168
|
|
143
169
|
alias + merge
|
144
170
|
|
145
|
-
# @deprecated will be removed in 2.0.0
|
146
|
-
alias | merge
|
147
|
-
|
148
171
|
# Prevents further modifications to the throttle instance.
|
149
172
|
#
|
150
173
|
# @see https://docs.ruby-lang.org/en/master/Object.html#method-i-freeze
|
@@ -155,17 +178,17 @@ class RedisThrottle
|
|
155
178
|
super
|
156
179
|
end
|
157
180
|
|
158
|
-
# Returns `true` if the `other` is an instance of {
|
159
|
-
# set of strategies.
|
181
|
+
# Returns `true` if the `other` is an instance of {RedisThrottle} with
|
182
|
+
# the same set of strategies.
|
160
183
|
#
|
161
184
|
# @example
|
162
185
|
# a = RedisThrottle
|
163
|
-
# .concurrency(:a, :
|
164
|
-
# .rate_limit(:b, :
|
186
|
+
# .concurrency(:a, limit: 1, ttl: 2)
|
187
|
+
# .rate_limit(:b, limit: 3, period: 4)
|
165
188
|
#
|
166
189
|
# b = RedisThrottle
|
167
|
-
# .rate_limit(:b, :
|
168
|
-
# .concurrency(:a, :
|
190
|
+
# .rate_limit(:b, limit: 3, period: 4)
|
191
|
+
# .concurrency(:a, limit: 1, ttl: 2)
|
169
192
|
#
|
170
193
|
# a == b # => true
|
171
194
|
#
|
@@ -180,69 +203,72 @@ class RedisThrottle
|
|
180
203
|
# it after the block.
|
181
204
|
#
|
182
205
|
# @example
|
183
|
-
# throttle = RedisThrottle.concurrency(:xxx, :
|
206
|
+
# throttle = RedisThrottle.concurrency(:xxx, limit: 1, ttl: 10)
|
184
207
|
#
|
185
|
-
# throttle.call { :aye } # => :aye
|
186
|
-
# throttle.call { :aye } # => :aye
|
208
|
+
# throttle.call(redis) { :aye } # => :aye
|
209
|
+
# throttle.call(redis) { :aye } # => :aye
|
187
210
|
#
|
188
|
-
# throttle.acquire
|
211
|
+
# throttle.acquire(redis)
|
189
212
|
#
|
190
|
-
# throttle.call { :aye } # => nil
|
213
|
+
# throttle.call(redis) { :aye } # => nil
|
191
214
|
#
|
192
|
-
# @param (see #
|
215
|
+
# @param redis (see Api#initialize)
|
216
|
+
# @param token (see #acquire)
|
193
217
|
# @return [Object] last satement of the block if execution lock was acquired.
|
194
218
|
# @return [nil] otherwise
|
195
|
-
def call(token: SecureRandom.uuid)
|
196
|
-
return unless acquire(token: token)
|
219
|
+
def call(redis, token: SecureRandom.uuid)
|
220
|
+
return unless acquire(redis, token: token)
|
197
221
|
|
198
222
|
begin
|
199
223
|
yield
|
200
224
|
ensure
|
201
|
-
release(token: token)
|
225
|
+
release(redis, token: token)
|
202
226
|
end
|
203
227
|
end
|
204
228
|
|
205
229
|
# Acquire execution lock.
|
206
230
|
#
|
207
231
|
# @example
|
208
|
-
# throttle = RedisThrottle.concurrency(:xxx, :
|
232
|
+
# throttle = RedisThrottle.concurrency(:xxx, limit: 1, ttl: 10)
|
209
233
|
#
|
210
|
-
# if (token = throttle.acquire)
|
234
|
+
# if (token = throttle.acquire(redis))
|
211
235
|
# # ... do something
|
212
236
|
# end
|
213
237
|
#
|
214
|
-
# throttle.release(:
|
238
|
+
# throttle.release(redis, token: token) if token
|
215
239
|
#
|
216
240
|
# @see #call
|
217
241
|
# @see #release
|
242
|
+
# @param redis (see Api#initialize)
|
218
243
|
# @param token [#to_s] Unit of work ID
|
219
244
|
# @return [#to_s] `token` as is if lock was acquired
|
220
245
|
# @return [nil] otherwise
|
221
|
-
def acquire(token: SecureRandom.uuid)
|
222
|
-
token if
|
246
|
+
def acquire(redis, token: SecureRandom.uuid)
|
247
|
+
token if Api.new(redis).acquire(strategies: @strategies, token: token.to_s)
|
223
248
|
end
|
224
249
|
|
225
250
|
# Release acquired execution lock. Notice that this affects {#concurrency}
|
226
251
|
# locks only.
|
227
252
|
#
|
228
253
|
# @example
|
229
|
-
# concurrency = RedisThrottle.concurrency(:xxx, :
|
230
|
-
# rate_limit = RedisThrottle.rate_limit(:xxx, :
|
254
|
+
# concurrency = RedisThrottle.concurrency(:xxx, limit: 1, ttl: 60)
|
255
|
+
# rate_limit = RedisThrottle.rate_limit(:xxx, limit: 1, period: 60)
|
231
256
|
# throttle = concurrency + rate_limit
|
232
257
|
#
|
233
|
-
# throttle.acquire(:
|
234
|
-
# throttle.release(:
|
258
|
+
# throttle.acquire(redis, token: "uno")
|
259
|
+
# throttle.release(redis, token: "uno")
|
235
260
|
#
|
236
|
-
# concurrency.acquire(:
|
237
|
-
# rate_limit.acquire(:
|
261
|
+
# concurrency.acquire(redis, token: "dos") # => "dos"
|
262
|
+
# rate_limit.acquire(redis, token: "dos") # => nil
|
238
263
|
#
|
239
264
|
# @see #acquire
|
240
265
|
# @see #reset
|
241
266
|
# @see #call
|
267
|
+
# @param redis (see Api#initialize)
|
242
268
|
# @param token [#to_s] Unit of work ID
|
243
269
|
# @return [void]
|
244
|
-
def release(token:)
|
245
|
-
|
270
|
+
def release(redis, token:)
|
271
|
+
Api.new(redis).release(strategies: @strategies, token: token.to_s)
|
246
272
|
|
247
273
|
nil
|
248
274
|
end
|
@@ -250,20 +276,21 @@ class RedisThrottle
|
|
250
276
|
# Flush all counters.
|
251
277
|
#
|
252
278
|
# @example
|
253
|
-
# throttle = RedisThrottle.concurrency(:xxx, :
|
279
|
+
# throttle = RedisThrottle.concurrency(:xxx, limit: 2, ttl: 60)
|
254
280
|
#
|
255
|
-
# thottle.acquire(:
|
256
|
-
# thottle.acquire(:
|
257
|
-
# thottle.acquire(:
|
281
|
+
# thottle.acquire(redis, token: "a") # => "a"
|
282
|
+
# thottle.acquire(redis, token: "b") # => "b"
|
283
|
+
# thottle.acquire(redis, token: "c") # => nil
|
258
284
|
#
|
259
|
-
# throttle.reset
|
285
|
+
# throttle.reset(redis)
|
260
286
|
#
|
261
|
-
# thottle.acquire(:
|
262
|
-
# thottle.acquire(:
|
287
|
+
# thottle.acquire(redis, token: "c") # => "c"
|
288
|
+
# thottle.acquire(redis, token: "d") # => "d"
|
263
289
|
#
|
290
|
+
# @param redis (see Api#initialize)
|
264
291
|
# @return [void]
|
265
|
-
def reset
|
266
|
-
|
292
|
+
def reset(redis)
|
293
|
+
Api.new(redis).reset(strategies: @strategies)
|
267
294
|
|
268
295
|
nil
|
269
296
|
end
|
@@ -271,13 +298,14 @@ class RedisThrottle
|
|
271
298
|
# Return usage info for all strategies of the throttle.
|
272
299
|
#
|
273
300
|
# @example
|
274
|
-
# throttle.info.each do |strategy, current_value|
|
301
|
+
# throttle.info(redis).each do |strategy, current_value|
|
275
302
|
# # ...
|
276
303
|
# end
|
277
304
|
#
|
305
|
+
# @param redis (see Api#initialize)
|
278
306
|
# @return (see Api#info)
|
279
|
-
def info
|
280
|
-
|
307
|
+
def info(redis)
|
308
|
+
Api.new(redis).info(strategies: @strategies)
|
281
309
|
end
|
282
310
|
|
283
311
|
protected
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-throttle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Zapparov
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: redis-prescription
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: '2.5'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
40
|
+
version: '2.5'
|
41
41
|
description:
|
42
42
|
email:
|
43
43
|
- alexey@zapparov.com
|
@@ -48,11 +48,9 @@ files:
|
|
48
48
|
- LICENSE.txt
|
49
49
|
- README.adoc
|
50
50
|
- lib/redis-throttle.rb
|
51
|
-
- lib/redis/throttle.rb
|
52
51
|
- lib/redis_throttle.rb
|
53
52
|
- lib/redis_throttle/api.lua
|
54
53
|
- lib/redis_throttle/api.rb
|
55
|
-
- lib/redis_throttle/class_methods.rb
|
56
54
|
- lib/redis_throttle/concurrency.rb
|
57
55
|
- lib/redis_throttle/rate_limit.rb
|
58
56
|
- lib/redis_throttle/version.rb
|
@@ -61,9 +59,9 @@ licenses:
|
|
61
59
|
- MIT
|
62
60
|
metadata:
|
63
61
|
homepage_uri: https://gitlab.com/ixti/redis-throttle
|
64
|
-
source_code_uri: https://gitlab.com/ixti/redis-throttle/tree/
|
62
|
+
source_code_uri: https://gitlab.com/ixti/redis-throttle/tree/v2.0.0
|
65
63
|
bug_tracker_uri: https://gitlab.com/ixti/redis-throttle/issues
|
66
|
-
changelog_uri: https://gitlab.com/ixti/redis-throttle/blob/
|
64
|
+
changelog_uri: https://gitlab.com/ixti/redis-throttle/blob/v2.0.0/CHANGES.md
|
67
65
|
rubygems_mfa_required: 'true'
|
68
66
|
post_install_message:
|
69
67
|
rdoc_options: []
|
@@ -80,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
78
|
- !ruby/object:Gem::Version
|
81
79
|
version: '0'
|
82
80
|
requirements: []
|
83
|
-
rubygems_version: 3.
|
81
|
+
rubygems_version: 3.2.33
|
84
82
|
signing_key:
|
85
83
|
specification_version: 4
|
86
84
|
summary: Redis based rate limit and concurrency throttling
|
data/lib/redis/throttle.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "../redis_throttle"
|
4
|
-
|
5
|
-
class Redis
|
6
|
-
# @deprecated Use ::RedisThrottle
|
7
|
-
class Throttle < RedisThrottle
|
8
|
-
class << self
|
9
|
-
attr_accessor :silence_deprecation_warning
|
10
|
-
end
|
11
|
-
|
12
|
-
self.silence_deprecation_warning = false
|
13
|
-
|
14
|
-
def initialize(*args, **kwargs, &block)
|
15
|
-
super(*args, **kwargs, &block)
|
16
|
-
|
17
|
-
return if self.class.silence_deprecation_warning
|
18
|
-
|
19
|
-
warn "#{self.class} usage was deprecated, please use RedisThrottle instead"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "./api"
|
4
|
-
|
5
|
-
class RedisThrottle
|
6
|
-
module ClassMethods
|
7
|
-
# Syntax sugar for {Throttle#concurrency}.
|
8
|
-
#
|
9
|
-
# @see #concurrency
|
10
|
-
# @param (see Throttle#initialize)
|
11
|
-
# @param (see Throttle#concurrency)
|
12
|
-
# @return (see Throttle#concurrency)
|
13
|
-
def concurrency(bucket, limit:, ttl:, redis: nil)
|
14
|
-
new(redis: redis).concurrency(bucket, limit: limit, ttl: ttl)
|
15
|
-
end
|
16
|
-
|
17
|
-
# Syntax sugar for {Throttle#rate_limit}.
|
18
|
-
#
|
19
|
-
# @see #concurrency
|
20
|
-
# @param (see Throttle#initialize)
|
21
|
-
# @param (see Throttle#rate_limit)
|
22
|
-
# @return (see Throttle#rate_limit)
|
23
|
-
def rate_limit(bucket, limit:, period:, redis: nil)
|
24
|
-
new(redis: redis).rate_limit(bucket, limit: limit, period: period)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Return usage info for all known (in use) strategies.
|
28
|
-
#
|
29
|
-
# @example
|
30
|
-
# Redis::Throttle.info(:match => "*_api").each do |strategy, current_value|
|
31
|
-
# # ...
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# @param match [#to_s]
|
35
|
-
# @return (see Api#info)
|
36
|
-
def info(match: "*", redis: nil)
|
37
|
-
api = Api.new(redis: redis)
|
38
|
-
strategies = api.strategies(match: match.to_s)
|
39
|
-
|
40
|
-
api.info(strategies: strategies)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|