redis-throttle 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|