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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88bc1f488ffad8621894918d48bbde5df0c68ef498ddaaf359d91f81914a27c5
4
- data.tar.gz: c219a0b2a6b66e1e5427bdab8260dcfc4f0121618fd8c340a3e892f92dad1192
3
+ metadata.gz: 30c315dd33f7e175c0e74b4dfd8344e889d7e856c96c786b87ebac29d07fcc3a
4
+ data.tar.gz: acfb600e437eb125b9bf279dd95315ce7fa40612f836f887003b360ae2aacceb
5
5
  SHA512:
6
- metadata.gz: 9e30ae0a0a4dbfb09778fc1cfcd02d3376b020fc83d4166a2ab6066725a4c2c0e8680f38ac26c127b6b0952ed4558ff9c3e82e0301dda0dc4db9bf831cb8c383
7
- data.tar.gz: 5cfb1b4e72a4b1014a131b50ddb028e41289b102016b54ba2a5eef4c03d2f7a5edd66b21c84924be54df1e01796d0c1c2c963a7cf8072bfc1ca7951bab983a47
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
- Open a pull request on GitHub.
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.3
1
+ 1.0.5
@@ -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
- def add(name, limit:, ttl:, redis: nil)
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
- @script_sha_1 ||= redis.script(:load, LUA_SCRIPT)
98
+ client = redis
99
+ @script_sha_1 ||= client.script(:load, LUA_SCRIPT)
100
+ attempts = 0
101
+
81
102
  begin
82
- redis.evalsha(@script_sha_1, Array(keys), Array(args))
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 = redis.script(:load, LUA_SCRIPT)
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 client to use
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.3
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: 2021-09-14 00:00:00.000000000 Z
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.0.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: []