sidekiq-throttled 0.11.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +51 -0
  3. data/.rubocop/layout.yml +24 -0
  4. data/.rubocop/lint.yml +41 -0
  5. data/.rubocop/metrics.yml +4 -0
  6. data/.rubocop/performance.yml +25 -0
  7. data/.rubocop/rspec.yml +3 -0
  8. data/.rubocop/style.yml +84 -0
  9. data/.rubocop.yml +13 -68
  10. data/.rubocop_todo.yml +10 -35
  11. data/.travis.yml +2 -1
  12. data/Appraisals +16 -0
  13. data/CHANGES.md +53 -0
  14. data/Gemfile +6 -5
  15. data/LICENSE.md +2 -1
  16. data/README.md +49 -18
  17. data/gemfiles/sidekiq_5.0.gemfile +6 -5
  18. data/gemfiles/sidekiq_5.1.gemfile +6 -5
  19. data/gemfiles/sidekiq_5.2.gemfile +6 -5
  20. data/gemfiles/sidekiq_6.0.gemfile +31 -0
  21. data/gemfiles/sidekiq_6.1.gemfile +31 -0
  22. data/gemfiles/sidekiq_6.2.gemfile +31 -0
  23. data/gemfiles/sidekiq_6.3.gemfile +31 -0
  24. data/lib/sidekiq/throttled/communicator/callbacks.rb +8 -9
  25. data/lib/sidekiq/throttled/communicator/listener.rb +3 -3
  26. data/lib/sidekiq/throttled/expirable_list.rb +1 -1
  27. data/lib/sidekiq/throttled/fetch.rb +34 -20
  28. data/lib/sidekiq/throttled/queue_name.rb +1 -1
  29. data/lib/sidekiq/throttled/registry.rb +2 -5
  30. data/lib/sidekiq/throttled/strategy/concurrency.rb +5 -5
  31. data/lib/sidekiq/throttled/strategy/threshold.rb +6 -5
  32. data/lib/sidekiq/throttled/strategy.rb +15 -20
  33. data/lib/sidekiq/throttled/strategy_collection.rb +69 -0
  34. data/lib/sidekiq/throttled/utils.rb +1 -1
  35. data/lib/sidekiq/throttled/version.rb +1 -1
  36. data/lib/sidekiq/throttled/web/stats.rb +2 -6
  37. data/lib/sidekiq/throttled/web/summary_fix.rb +3 -2
  38. data/lib/sidekiq/throttled/web/throttled.html.erb +6 -2
  39. data/lib/sidekiq/throttled/web.rb +1 -1
  40. data/lib/sidekiq/throttled/worker.rb +2 -2
  41. data/lib/sidekiq/throttled.rb +14 -2
  42. data/sidekiq-throttled.gemspec +3 -1
  43. metadata +21 -9
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # Sidekiq::Throttled
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/sidekiq-throttled.svg)](http://rubygems.org/gems/sidekiq-throttled)
4
- [![Build Status](https://travis-ci.org/sensortower/sidekiq-throttled.svg?branch=master)](https://travis-ci.org/sensortower/sidekiq-throttled)
5
- [![Code Climate](https://codeclimate.com/github/sensortower/sidekiq-throttled.svg?branch=master)](https://codeclimate.com/github/sensortower/sidekiq-throttled)
6
- [![Coverage Status](https://coveralls.io/repos/github/sensortower/sidekiq-throttled/badge.svg?branch=master)](https://coveralls.io/github/sensortower/sidekiq-throttled?branch=master)
7
- [![API Docs](http://inch-ci.org/github/sensortower/sidekiq-throttled.svg?branch=master)](http://inch-ci.org/github/sensortower/sidekiq-throttled)
3
+ [![Latest Version](https://badge.fury.io/rb/sidekiq-throttled.svg)](http://rubygems.org/gems/sidekiq-throttled)
4
+ [![CI Status](https://github.com/sensortower/sidekiq-throttled/workflows/CI/badge.svg?branch=master)](https://github.com/sensortower/sidekiq-throttled/actions?query=workflow%3ACI+branch%3Amaster)
5
+ [![Code Quality](https://codeclimate.com/github/sensortower/sidekiq-throttled.svg?branch=master)](https://codeclimate.com/github/sensortower/sidekiq-throttled)
6
+ [![Code Coverage](https://coveralls.io/repos/github/sensortower/sidekiq-throttled/badge.svg?branch=master)](https://coveralls.io/github/sensortower/sidekiq-throttled?branch=master)
7
+ [![API Docs Quality](http://inch-ci.org/github/sensortower/sidekiq-throttled.svg?branch=master)](http://inch-ci.org/github/sensortower/sidekiq-throttled)
8
+ [![API Docs](https://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/gems/sidekiq-throttled)
8
9
 
9
10
  Concurrency and threshold throttling for [Sidekiq][sidekiq].
10
11
 
11
-
12
12
  ## Installation
13
13
 
14
14
  Add this line to your application's Gemfile:
@@ -36,6 +36,9 @@ require "sidekiq/throttled"
36
36
  Sidekiq::Throttled.setup!
37
37
  ```
38
38
 
39
+ Load order can be an issue if you are using other Sidekiq plugins and/or middleware.
40
+ To prevent any problems, add the `.setup!` call to the bottom of your init file.
41
+
39
42
  Once you've done that you can include `Sidekiq::Throttled::Worker` to your
40
43
  job classes and configure throttling:
41
44
 
@@ -46,12 +49,12 @@ class MyWorker
46
49
 
47
50
  sidekiq_options :queue => :my_queue
48
51
 
49
- sidekiq_throttle({
52
+ sidekiq_throttle(
50
53
  # Allow maximum 10 concurrent jobs of this class at a time.
51
54
  :concurrency => { :limit => 10 },
52
55
  # Allow maximum 1K jobs being processed within one hour window.
53
56
  :threshold => { :limit => 1_000, :period => 1.hour }
54
- })
57
+ )
55
58
 
56
59
  def perform
57
60
  # ...
@@ -75,11 +78,11 @@ class MyWorker
75
78
 
76
79
  sidekiq_options :queue => :my_queue
77
80
 
78
- sidekiq_throttle({
81
+ sidekiq_throttle(
79
82
  :concurrency => { :limit => 10 },
80
83
  :threshold => { :limit => 100, :period => 1.hour }
81
84
  :observer => MY_OBSERVER
82
- })
85
+ )
83
86
 
84
87
  def perform(*args)
85
88
  # ...
@@ -88,7 +91,7 @@ end
88
91
  ```
89
92
 
90
93
  Observer will receive `strategy, *args` arguments, where `strategy` is a Symbol
91
- `:concurrency` or `:threshold`, and `*args` are the arguements that were passed
94
+ `:concurrency` or `:threshold`, and `*args` are the arguments that were passed
92
95
  to the job.
93
96
 
94
97
 
@@ -103,10 +106,10 @@ class MyWorker
103
106
 
104
107
  sidekiq_options :queue => :my_queue
105
108
 
106
- sidekiq_throttle({
109
+ sidekiq_throttle(
107
110
  # Allow maximum 10 concurrent jobs per user at a time.
108
111
  :concurrency => { :limit => 10, :key_suffix => -> (user_id) { user_id } }
109
- })
112
+ )
110
113
 
111
114
  def perform(user_id)
112
115
  # ...
@@ -125,7 +128,7 @@ class MyWorker
125
128
 
126
129
  sidekiq_options :queue => :my_queue
127
130
 
128
- sidekiq_throttle({
131
+ sidekiq_throttle(
129
132
  # Allow maximum 1000 concurrent jobs of this class at a time for VIPs and 10 for all other users.
130
133
  :concurrency => {
131
134
  :limit => ->(user_id) { User.vip?(user_id) ? 1_000 : 10 },
@@ -136,7 +139,7 @@ class MyWorker
136
139
  :limit => ->(user_id) { User.vip?(user_id) ? 1_000 : 10 },
137
140
  :period => ->(user_id) { User.vip?(user_id) ? 1.hour : 1.day },
138
141
  :key_suffix => ->(user_id) { User.vip?(user_id) ? "vip" : "std" }
139
- })
142
+ )
140
143
 
141
144
  def perform(user_id)
142
145
  # ...
@@ -144,6 +147,30 @@ class MyWorker
144
147
  end
145
148
  ```
146
149
 
150
+ You also can use several different keys to throttle one worker.
151
+
152
+ ``` ruby
153
+ class MyWorker
154
+ include Sidekiq::Worker
155
+ include Sidekiq::Throttled::Worker
156
+
157
+ sidekiq_options :queue => :my_queue
158
+
159
+ sidekiq_throttle(
160
+ # Allow maximum 10 concurrent jobs per project at a time and maximum 2 jobs per user
161
+ :concurrency => [
162
+ { :limit => 10, :key_suffix => -> (project_id, user_id) { project_id } },
163
+ { :limit => 2, :key_suffix => -> (project_id, user_id) { user_id } }
164
+ ]
165
+ # For :threshold it works the same
166
+ )
167
+
168
+ def perform(project_id, user_id)
169
+ # ...
170
+ end
171
+ end
172
+ ```
173
+
147
174
  **NB** Don't forget to specify `:key_suffix` and make it return different values
148
175
  if you are using dynamic limit/period options. Otherwise you risk getting into
149
176
  some trouble.
@@ -206,9 +233,9 @@ end
206
233
  This library aims to support and is [tested against][travis] the following Ruby
207
234
  versions:
208
235
 
209
- * Ruby 2.4.x
210
- * Ruby 2.5.x
211
236
  * Ruby 2.6.x
237
+ * Ruby 2.7.x
238
+ * Ruby 3.0.x
212
239
 
213
240
  If something doesn't work on one of these versions, it's a bug.
214
241
 
@@ -231,6 +258,10 @@ This library aims to support work with following [Sidekiq][sidekiq] versions:
231
258
  * Sidekiq 5.0.x
232
259
  * Sidekiq 5.1.x
233
260
  * Sidekiq 5.2.x
261
+ * Sidekiq 6.0.x
262
+ * Sidekiq 6.1.x
263
+ * Sidekiq 6.2.x
264
+ * Sidekiq 6.3.x
234
265
 
235
266
 
236
267
  ## Contributing
@@ -258,7 +289,7 @@ Don't forget to run `appraisal update` after any changes to `Gemfile`.
258
289
 
259
290
  ## Copyright
260
291
 
261
- Copyright (c) 2015-2018 SensorTower Inc.
292
+ Copyright (c) 2020-2021 Alexey Zapparov, SensorTower Inc.
262
293
  See LICENSE.md for further details.
263
294
 
264
295
 
@@ -5,8 +5,9 @@ source "https://rubygems.org"
5
5
  gem "appraisal"
6
6
  gem "rake"
7
7
  gem "rspec"
8
- gem "rubocop", "~> 0.58.0", require: false
9
- gem "rubocop-rspec", "~> 1.29.1", require: false
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
10
11
  gem "sidekiq", "~> 5.0.0"
11
12
 
12
13
  group :development do
@@ -17,13 +18,13 @@ group :development do
17
18
  end
18
19
 
19
20
  group :test do
21
+ gem "apparition"
20
22
  gem "capybara"
21
23
  gem "coveralls", require: false
22
- gem "poltergeist"
23
24
  gem "puma"
24
25
  gem "rack-test"
25
- gem "simplecov", ">= 0.9"
26
- gem "sinatra", "~> 1.4", ">= 1.4.6"
26
+ gem "simplecov"
27
+ gem "sinatra"
27
28
  gem "timecop"
28
29
  end
29
30
 
@@ -5,8 +5,9 @@ source "https://rubygems.org"
5
5
  gem "appraisal"
6
6
  gem "rake"
7
7
  gem "rspec"
8
- gem "rubocop", "~> 0.58.0", require: false
9
- gem "rubocop-rspec", "~> 1.29.1", require: false
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
10
11
  gem "sidekiq", "~> 5.1.0"
11
12
 
12
13
  group :development do
@@ -17,13 +18,13 @@ group :development do
17
18
  end
18
19
 
19
20
  group :test do
21
+ gem "apparition"
20
22
  gem "capybara"
21
23
  gem "coveralls", require: false
22
- gem "poltergeist"
23
24
  gem "puma"
24
25
  gem "rack-test"
25
- gem "simplecov", ">= 0.9"
26
- gem "sinatra", "~> 1.4", ">= 1.4.6"
26
+ gem "simplecov"
27
+ gem "sinatra"
27
28
  gem "timecop"
28
29
  end
29
30
 
@@ -5,8 +5,9 @@ source "https://rubygems.org"
5
5
  gem "appraisal"
6
6
  gem "rake"
7
7
  gem "rspec"
8
- gem "rubocop", "~> 0.58.0", require: false
9
- gem "rubocop-rspec", "~> 1.29.1", require: false
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
10
11
  gem "sidekiq", "~> 5.2.0"
11
12
 
12
13
  group :development do
@@ -17,13 +18,13 @@ group :development do
17
18
  end
18
19
 
19
20
  group :test do
21
+ gem "apparition"
20
22
  gem "capybara"
21
23
  gem "coveralls", require: false
22
- gem "poltergeist"
23
24
  gem "puma"
24
25
  gem "rack-test"
25
- gem "simplecov", ">= 0.9"
26
- gem "sinatra", "~> 1.4", ">= 1.4.6"
26
+ gem "simplecov"
27
+ gem "sinatra"
27
28
  gem "timecop"
28
29
  end
29
30
 
@@ -0,0 +1,31 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
11
+ gem "sidekiq", "~> 6.0.0"
12
+
13
+ group :development do
14
+ gem "byebug"
15
+ gem "guard", require: false
16
+ gem "guard-rspec", require: false
17
+ gem "guard-rubocop", require: false
18
+ end
19
+
20
+ group :test do
21
+ gem "apparition"
22
+ gem "capybara"
23
+ gem "coveralls", require: false
24
+ gem "puma"
25
+ gem "rack-test"
26
+ gem "simplecov"
27
+ gem "sinatra"
28
+ gem "timecop"
29
+ end
30
+
31
+ gemspec path: "../"
@@ -0,0 +1,31 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
11
+ gem "sidekiq", "~> 6.1.0"
12
+
13
+ group :development do
14
+ gem "byebug"
15
+ gem "guard", require: false
16
+ gem "guard-rspec", require: false
17
+ gem "guard-rubocop", require: false
18
+ end
19
+
20
+ group :test do
21
+ gem "apparition"
22
+ gem "capybara"
23
+ gem "coveralls", require: false
24
+ gem "puma"
25
+ gem "rack-test"
26
+ gem "simplecov"
27
+ gem "sinatra"
28
+ gem "timecop"
29
+ end
30
+
31
+ gemspec path: "../"
@@ -0,0 +1,31 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
11
+ gem "sidekiq", "~> 6.2.0"
12
+
13
+ group :development do
14
+ gem "byebug"
15
+ gem "guard", require: false
16
+ gem "guard-rspec", require: false
17
+ gem "guard-rubocop", require: false
18
+ end
19
+
20
+ group :test do
21
+ gem "apparition"
22
+ gem "capybara"
23
+ gem "coveralls", require: false
24
+ gem "puma"
25
+ gem "rack-test"
26
+ gem "simplecov"
27
+ gem "sinatra"
28
+ gem "timecop"
29
+ end
30
+
31
+ gemspec path: "../"
@@ -0,0 +1,31 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rake"
7
+ gem "rspec"
8
+ gem "rubocop", "~> 0.90.0", require: false
9
+ gem "rubocop-performance", "~> 1.8.0", require: false
10
+ gem "rubocop-rspec", "~> 1.43.2", require: false
11
+ gem "sidekiq", "~> 6.3.0"
12
+
13
+ group :development do
14
+ gem "byebug"
15
+ gem "guard", require: false
16
+ gem "guard-rspec", require: false
17
+ gem "guard-rubocop", require: false
18
+ end
19
+
20
+ group :test do
21
+ gem "apparition"
22
+ gem "capybara"
23
+ gem "coveralls", require: false
24
+ gem "puma"
25
+ gem "rack-test"
26
+ gem "simplecov"
27
+ gem "sinatra"
28
+ gem "timecop"
29
+ end
30
+
31
+ gemspec path: "../"
@@ -43,6 +43,7 @@ module Sidekiq
43
43
  # @return [self]
44
44
  def on(event, &handler)
45
45
  raise ArgumentError, "No block given" unless handler
46
+
46
47
  @mutex.synchronize { @handlers[event.to_s] << handler }
47
48
  self
48
49
  end
@@ -54,17 +55,15 @@ module Sidekiq
54
55
  # @return [void]
55
56
  def run(event, payload = nil)
56
57
  @mutex.synchronize do
57
- Fiber.new do
58
+ fiber = Fiber.new do
58
59
  @handlers[event.to_s].each do |callback|
59
- begin
60
- callback.call(payload)
61
- rescue => e
62
- handle_exception(e, {
63
- :context => "sidekiq:throttled"
64
- })
65
- end
60
+ callback.call(payload)
61
+ rescue => e
62
+ handle_exception(e, :context => "sidekiq:throttled")
66
63
  end
67
- end.resume
64
+ end
65
+
66
+ fiber.resume
68
67
  end
69
68
  end
70
69
  end
@@ -62,7 +62,7 @@ module Sidekiq
62
62
  # - `Exception` is recorded to the log and re-raised.
63
63
  #
64
64
  # @return [void]
65
- def listen
65
+ def listen # rubocop:disable Metrics/MethodLength
66
66
  subscribe
67
67
  rescue Sidekiq::Shutdown
68
68
  @terminated = true
@@ -88,7 +88,7 @@ module Sidekiq
88
88
  # @see http://redis.io/commands/subscribe
89
89
  # @see Callbacks#run
90
90
  # @return [void]
91
- def subscribe
91
+ def subscribe # rubocop:disable Metrics/MethodLength
92
92
  Sidekiq.redis do |conn|
93
93
  conn.subscribe @channel do |on|
94
94
  on.subscribe do
@@ -97,7 +97,7 @@ module Sidekiq
97
97
  end
98
98
 
99
99
  on.message do |_channel, data|
100
- message, payload = Marshal.load(data)
100
+ message, payload = Marshal.load(data) # rubocop:disable Security/MarshalLoad:
101
101
  @callbacks.run("message:#{message}", payload)
102
102
  end
103
103
  end
@@ -11,7 +11,7 @@ module Sidekiq
11
11
  #
12
12
  # ## Implementation
13
13
  #
14
- # Internally list holds an array of arrays. Thus ecah element is a tuple of
14
+ # Internally list holds an array of arrays. Thus each element is a tuple of
15
15
  # monotonic timestamp (when element was added) and element itself:
16
16
  #
17
17
  # [
@@ -12,16 +12,47 @@ module Sidekiq
12
12
  #
13
13
  # @private
14
14
  class Fetch
15
+ module BulkRequeue
16
+ # Requeues all given units as a single operation.
17
+ #
18
+ # @see http://www.rubydoc.info/github/redis/redis-rb/master/Redis#pipelined-instance_method
19
+ # @param [Array<Fetch::UnitOfWork>] units
20
+ # @return [void]
21
+ def bulk_requeue(units, _options)
22
+ return if units.empty?
23
+
24
+ Sidekiq.logger.debug { "Re-queueing terminated jobs" }
25
+ Sidekiq.redis { |conn| conn.pipelined { units.each(&:requeue) } }
26
+ Sidekiq.logger.info("Pushed #{units.size} jobs back to Redis")
27
+ rescue => e
28
+ Sidekiq.logger.warn("Failed to requeue #{units.size} jobs: #{e}")
29
+ end
30
+ end
31
+
32
+ # https://github.com/mperham/sidekiq/commit/fce05c9d4b4c0411c982078a4cf3a63f20f739bc
33
+ if Gem::Version.new(Sidekiq::VERSION) < Gem::Version.new("6.1.0")
34
+ extend BulkRequeue
35
+ else
36
+ include BulkRequeue
37
+ end
15
38
  # Timeout to sleep between fetch retries in case of no job received,
16
39
  # as well as timeout to wait for redis to give us something to work.
17
40
  TIMEOUT = 2
18
41
 
19
42
  # Initializes fetcher instance.
43
+ # @param options [Hash]
44
+ # @option options [Integer] :throttled_queue_cooldown (TIMEOUT)
45
+ # Min delay in seconds before queue will be polled again after
46
+ # throttled job.
47
+ # @option options [Boolean] :strict (false)
48
+ # @option options [Array<#to_s>] :queue
20
49
  def initialize(options)
21
- @paused = ExpirableList.new(TIMEOUT)
50
+ @paused = ExpirableList.new(options.fetch(:throttled_queue_cooldown, TIMEOUT))
22
51
 
23
- @strict = options[:strict]
24
- @queues = options[:queues].map { |q| QueueName.expand q }
52
+ @strict = options.fetch(:strict, false)
53
+ @queues = options.fetch(:queues).map { |q| QueueName.expand q }
54
+
55
+ raise ArgumentError, "empty :queues" if @queues.empty?
25
56
 
26
57
  @queues.uniq! if @strict
27
58
  end
@@ -42,23 +73,6 @@ module Sidekiq
42
73
  nil
43
74
  end
44
75
 
45
- class << self
46
- # Requeues all given units as a single operation.
47
- #
48
- # @see http://www.rubydoc.info/github/redis/redis-rb/master/Redis#pipelined-instance_method
49
- # @param [Array<Fetch::UnitOfWork>] units
50
- # @return [void]
51
- def bulk_requeue(units, _options)
52
- return if units.empty?
53
-
54
- Sidekiq.logger.debug { "Re-queueing terminated jobs" }
55
- Sidekiq.redis { |conn| conn.pipelined { units.each(&:requeue) } }
56
- Sidekiq.logger.info("Pushed #{units.size} jobs back to Redis")
57
- rescue => e
58
- Sidekiq.logger.warn("Failed to requeue #{units.size} jobs: #{e}")
59
- end
60
- end
61
-
62
76
  private
63
77
 
64
78
  # Tries to pop pair of `queue` and job `message` out of sidekiq queues.
@@ -7,7 +7,7 @@ module Sidekiq
7
7
  # @private
8
8
  module QueueName
9
9
  # RegExp used to stip out any redisr-namespace prefixes with `queue:`.
10
- QUEUE_NAME_PREFIX_RE = /.*queue:/
10
+ QUEUE_NAME_PREFIX_RE = %r{.*queue:}.freeze
11
11
  private_constant :QUEUE_NAME_PREFIX_RE
12
12
 
13
13
  class << self
@@ -18,20 +18,16 @@ module Sidekiq
18
18
 
19
19
  # Adds strategy to the registry.
20
20
  #
21
- # @note prints a warning to STDERR upon duplicate strategy name
22
21
  # @param (see Strategy#initialize)
23
22
  # @return [Strategy]
24
23
  def add(name, **kwargs)
25
24
  name = name.to_s
26
25
 
27
- warn "Duplicate strategy name: #{name}" if @strategies[name]
28
-
29
26
  @strategies[name] = Strategy.new(name, **kwargs)
30
27
  end
31
28
 
32
29
  # Adds alias for existing strategy.
33
30
  #
34
- # @note prints a warning to STDERR upon duplicate strategy name
35
31
  # @param (#to_s) new_name
36
32
  # @param (#to_s) old_name
37
33
  # @raise [RuntimeError] if no strategy found with `old_name`
@@ -40,7 +36,6 @@ module Sidekiq
40
36
  new_name = new_name.to_s
41
37
  old_name = old_name.to_s
42
38
 
43
- warn "Duplicate strategy name: #{new_name}" if @strategies[new_name]
44
39
  raise "Strategy not found: #{old_name}" unless @strategies[old_name]
45
40
 
46
41
  @aliases[new_name] = @strategies[old_name]
@@ -74,6 +69,7 @@ module Sidekiq
74
69
  # @return [Registry]
75
70
  def each
76
71
  return to_enum(__method__) unless block_given?
72
+
77
73
  @strategies.each { |*args| yield(*args) }
78
74
  self
79
75
  end
@@ -88,6 +84,7 @@ module Sidekiq
88
84
  # @return [Registry]
89
85
  def each_with_static_keys
90
86
  return to_enum(__method__) unless block_given?
87
+
91
88
  @strategies.each do |name, strategy|
92
89
  yield(name, strategy) unless strategy.dynamic?
93
90
  end
@@ -46,12 +46,12 @@ module Sidekiq
46
46
  return false unless job_limit
47
47
  return true if job_limit <= 0
48
48
 
49
- kwargs = {
50
- :keys => [key(job_args)],
51
- :argv => [jid.to_s, job_limit, @ttl, Time.now.to_f]
52
- }
49
+ keys = [key(job_args)]
50
+ argv = [jid.to_s, job_limit, @ttl, Time.now.to_f]
53
51
 
54
- Sidekiq.redis { |redis| 1 == SCRIPT.eval(redis, kwargs) }
52
+ Sidekiq.redis do |redis|
53
+ 1 == SCRIPT.eval(redis, :keys => keys, :argv => argv)
54
+ end
55
55
  end
56
56
 
57
57
  # @return [Integer] Current count of jobs
@@ -48,6 +48,7 @@ module Sidekiq
48
48
  # @return [Float] Period in seconds
49
49
  def period(job_args = nil)
50
50
  return @period.to_f unless @period.respond_to? :call
51
+
51
52
  @period.call(*job_args).to_f
52
53
  end
53
54
 
@@ -62,12 +63,12 @@ module Sidekiq
62
63
  return false unless job_limit
63
64
  return true if job_limit <= 0
64
65
 
65
- kwargs = {
66
- :keys => [key(job_args)],
67
- :argv => [job_limit, period(job_args), Time.now.to_f]
68
- }
66
+ keys = [key(job_args)]
67
+ argv = [job_limit, period(job_args), Time.now.to_f]
69
68
 
70
- Sidekiq.redis { |redis| 1 == SCRIPT.eval(redis, kwargs) }
69
+ Sidekiq.redis do |redis|
70
+ 1 == SCRIPT.eval(redis, :keys => keys, :argv => argv)
71
+ end
71
72
  end
72
73
 
73
74
  # @return [Integer] Current count of jobs