simple_throttle 1.0.3 → 1.0.5
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/CHANGELOG.md +11 -0
- data/README.md +1 -1
- data/VERSION +1 -1
- data/lib/simple_throttle.rb +39 -8
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30c315dd33f7e175c0e74b4dfd8344e889d7e856c96c786b87ebac29d07fcc3a
|
4
|
+
data.tar.gz: acfb600e437eb125b9bf279dd95315ce7fa40612f836f887003b360ae2aacceb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89d1b64043ee7f6460be93bb12ac50728e31ede360bcaa68191cb84087d50fe7db4386d8d24eba380c37a9426df78cb26c0685da75d7f6610e244e332be2821c
|
7
|
+
data.tar.gz: 47598bdce624ab1effbefbfc36d8860f3e017a7ecb2213cdd46d8c67e681583df62bdaf1270f77f6d4e83a88de0c0222c92c3a141fb9bfc3340cbee3bf0914a3
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## 1.0.5
|
8
|
+
|
9
|
+
### Added
|
10
|
+
- Make loading lua script play better with Redis clusters.
|
11
|
+
- Handle failures loading lua script on Redis server to prevent infinite loop.
|
12
|
+
|
13
|
+
## 1.0.4
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- Fix wait_time method to match the documentation from [bc-swoop](https://github.com/bc-swoop)
|
17
|
+
|
7
18
|
## 1.0.3
|
8
19
|
|
9
20
|
### Changed
|
data/README.md
CHANGED
@@ -60,7 +60,7 @@ $ gem install simple_throttle
|
|
60
60
|
|
61
61
|
## Contributing
|
62
62
|
|
63
|
-
|
63
|
+
Fork the repository and open a pull request on GitHub.
|
64
64
|
|
65
65
|
Please use the [standardrb](https://github.com/testdouble/standard) syntax and lint your code with `standardrb --fix` before submitting.
|
66
66
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.5
|
data/lib/simple_throttle.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "redis"
|
4
|
+
|
4
5
|
# Create a simple throttle that can be used to limit the number of request for a resouce
|
5
6
|
# per time period. These objects are thread safe.
|
6
7
|
class SimpleThrottle
|
@@ -41,7 +42,15 @@ class SimpleThrottle
|
|
41
42
|
|
42
43
|
class << self
|
43
44
|
# Add a global throttle that can be referenced later with the [] method.
|
44
|
-
|
45
|
+
# This can be used to configure global throttles that you want to setup once
|
46
|
+
# and then use in multiple places.
|
47
|
+
#
|
48
|
+
# @param name [String] unique name for the throttle
|
49
|
+
# @param ttl [Numeric] number of seconds that the throttle will remain active
|
50
|
+
# @param limit [Integer] number of allowed requests within the throttle ttl
|
51
|
+
# @param redis [Redis, Proc] Redis instance to use or a Proc that yields a Redos instance
|
52
|
+
# @return [void]
|
53
|
+
def add(name, ttl:, limit:, redis: nil)
|
45
54
|
@lock.synchronize do
|
46
55
|
@throttles ||= {}
|
47
56
|
@throttles[name.to_s] = new(name, limit: limit, ttl: ttl, redis: redis)
|
@@ -49,6 +58,9 @@ class SimpleThrottle
|
|
49
58
|
end
|
50
59
|
|
51
60
|
# Returns a globally defined throttle with the specfied name.
|
61
|
+
#
|
62
|
+
# @param name [String, Symbol] name of the throttle
|
63
|
+
# @return [SimpleThrottle]
|
52
64
|
def [](name)
|
53
65
|
if defined?(@throttles) && @throttles
|
54
66
|
@throttles[name.to_s]
|
@@ -60,11 +72,17 @@ class SimpleThrottle
|
|
60
72
|
# it will be invoked at runtime to get the instance. Use this method if your Redis instance
|
61
73
|
# isn't constant (for example if you're in a forking environment and re-initialize connections
|
62
74
|
# on fork)
|
75
|
+
#
|
76
|
+
# @param client [Redis, Proc]
|
77
|
+
# @yieldreturn [Redis]
|
78
|
+
# @return [void]
|
63
79
|
def set_redis(client = nil, &block)
|
64
80
|
@redis_client = (client || block)
|
65
81
|
end
|
66
82
|
|
67
83
|
# Return the Redis instance where the throttles are stored.
|
84
|
+
#
|
85
|
+
# @return [Redis]
|
68
86
|
def redis
|
69
87
|
@redis_client ||= Redis.new
|
70
88
|
if @redis_client.is_a?(Proc)
|
@@ -77,12 +95,16 @@ class SimpleThrottle
|
|
77
95
|
private
|
78
96
|
|
79
97
|
def execute_lua_script(redis:, keys:, args:)
|
80
|
-
|
98
|
+
client = redis
|
99
|
+
@script_sha_1 ||= client.script(:load, LUA_SCRIPT)
|
100
|
+
attempts = 0
|
101
|
+
|
81
102
|
begin
|
82
|
-
|
103
|
+
client.evalsha(@script_sha_1, Array(keys), Array(args))
|
83
104
|
rescue Redis::CommandError => e
|
84
|
-
if e.message.include?("NOSCRIPT")
|
85
|
-
@script_sha_1 =
|
105
|
+
if e.message.include?("NOSCRIPT") && attempts < 2
|
106
|
+
@script_sha_1 = client.script(:load, LUA_SCRIPT)
|
107
|
+
attempts += 1
|
86
108
|
retry
|
87
109
|
else
|
88
110
|
raise e
|
@@ -93,11 +115,12 @@ class SimpleThrottle
|
|
93
115
|
|
94
116
|
attr_reader :name, :limit, :ttl
|
95
117
|
|
96
|
-
# Create a new throttle
|
118
|
+
# Create a new throttle.
|
119
|
+
#
|
97
120
|
# @param name [String] unique name for the throttle
|
98
121
|
# @param ttl [Numeric] number of seconds that the throttle will remain active
|
99
122
|
# @param limit [Integer] number of allowed requests within the throttle ttl
|
100
|
-
# @param redis [Redis] Redis
|
123
|
+
# @param redis [Redis, Proc] Redis instance to use or a Proc that yields a Redos instance
|
101
124
|
def initialize(name, ttl:, limit:, redis: nil)
|
102
125
|
@name = name.to_s
|
103
126
|
@name = name.dup.freeze unless name.frozen?
|
@@ -108,17 +131,23 @@ class SimpleThrottle
|
|
108
131
|
|
109
132
|
# Returns true if the limit for the throttle has not been reached yet. This method
|
110
133
|
# will also track the throttled resource as having been invoked on each call.
|
134
|
+
#
|
135
|
+
# @return [Boolean]
|
111
136
|
def allowed!
|
112
137
|
size = current_size(true)
|
113
138
|
size < limit
|
114
139
|
end
|
115
140
|
|
116
141
|
# Reset a throttle back to zero.
|
142
|
+
#
|
143
|
+
# @return [void]
|
117
144
|
def reset!
|
118
145
|
redis_client.del(redis_key)
|
119
146
|
end
|
120
147
|
|
121
148
|
# Peek at the current number for throttled calls being tracked.
|
149
|
+
#
|
150
|
+
# @return [Integer]
|
122
151
|
def peek
|
123
152
|
current_size(false)
|
124
153
|
end
|
@@ -126,6 +155,8 @@ class SimpleThrottle
|
|
126
155
|
# Returns when the next resource call should be allowed. Note that this doesn't guarantee that
|
127
156
|
# calling allow! will return true if the wait time is zero since other processes or threads can
|
128
157
|
# claim the resource.
|
158
|
+
#
|
159
|
+
# @return [Float]
|
129
160
|
def wait_time
|
130
161
|
if peek < limit
|
131
162
|
0.0
|
@@ -133,7 +164,7 @@ class SimpleThrottle
|
|
133
164
|
first = redis_client.lindex(redis_key, 0).to_f / 1000.0
|
134
165
|
delta = Time.now.to_f - first
|
135
166
|
delta = 0.0 if delta < 0
|
136
|
-
delta
|
167
|
+
ttl - delta
|
137
168
|
end
|
138
169
|
end
|
139
170
|
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_throttle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- We Heart It
|
8
8
|
- Brian Durand
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-03-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
|
-
description:
|
42
|
+
description:
|
43
43
|
email:
|
44
44
|
- dev@weheartit.com
|
45
45
|
- bbdurand@gmail.com
|
@@ -57,7 +57,7 @@ homepage: https://github.com/weheartit/simple_throttle
|
|
57
57
|
licenses:
|
58
58
|
- MIT
|
59
59
|
metadata: {}
|
60
|
-
post_install_message:
|
60
|
+
post_install_message:
|
61
61
|
rdoc_options: []
|
62
62
|
require_paths:
|
63
63
|
- lib
|
@@ -72,8 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: '0'
|
74
74
|
requirements: []
|
75
|
-
rubygems_version: 3.
|
76
|
-
signing_key:
|
75
|
+
rubygems_version: 3.2.22
|
76
|
+
signing_key:
|
77
77
|
specification_version: 4
|
78
78
|
summary: Simple redis backed throttling mechanism to limit access to a resource
|
79
79
|
test_files: []
|