sidekiq-throttled 0.10.0 → 0.14.1

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +54 -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 +8 -0
  13. data/CHANGES.md +28 -0
  14. data/Gemfile +6 -5
  15. data/LICENSE.md +1 -1
  16. data/README.md +75 -15
  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/lib/sidekiq/throttled/communicator/callbacks.rb +7 -6
  23. data/lib/sidekiq/throttled/communicator/listener.rb +3 -3
  24. data/lib/sidekiq/throttled/expirable_list.rb +1 -1
  25. data/lib/sidekiq/throttled/fetch.rb +34 -20
  26. data/lib/sidekiq/throttled/queue_name.rb +1 -1
  27. data/lib/sidekiq/throttled/registry.rb +2 -5
  28. data/lib/sidekiq/throttled/strategy/concurrency.rb +5 -5
  29. data/lib/sidekiq/throttled/strategy/threshold.rb +6 -5
  30. data/lib/sidekiq/throttled/strategy.rb +23 -14
  31. data/lib/sidekiq/throttled/strategy_collection.rb +70 -0
  32. data/lib/sidekiq/throttled/utils.rb +1 -1
  33. data/lib/sidekiq/throttled/version.rb +1 -1
  34. data/lib/sidekiq/throttled/web/stats.rb +2 -6
  35. data/lib/sidekiq/throttled/web/summary_fix.rb +3 -2
  36. data/lib/sidekiq/throttled/web/throttled.html.erb +6 -2
  37. data/lib/sidekiq/throttled/web.rb +1 -1
  38. data/lib/sidekiq/throttled/worker.rb +2 -2
  39. data/lib/sidekiq/throttled.rb +14 -2
  40. data/sidekiq-throttled.gemspec +2 -0
  41. metadata +18 -8
@@ -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.82.0", require: false
9
+ gem "rubocop-performance", "~>1.5.2", require: false
10
+ gem "rubocop-rspec", "~> 1.39.0", 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.82.0", require: false
9
+ gem "rubocop-performance", "~>1.5.2", require: false
10
+ gem "rubocop-rspec", "~> 1.39.0", 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.82.0", require: false
9
+ gem "rubocop-performance", "~>1.5.2", require: false
10
+ gem "rubocop-rspec", "~> 1.39.0", 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.82.0", require: false
9
+ gem "rubocop-performance", "~>1.5.2", require: false
10
+ gem "rubocop-rspec", "~> 1.39.0", 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.82.0", require: false
9
+ gem "rubocop-performance", "~>1.5.2", require: false
10
+ gem "rubocop-rspec", "~> 1.39.0", 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: "../"
@@ -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
@@ -52,19 +53,19 @@ module Sidekiq
52
53
  # @param [#to_s] event
53
54
  # @param [Object] payload
54
55
  # @return [void]
55
- def run(event, payload = nil)
56
+ def run(event, payload = nil) # rubocop:disable Metrics/MethodLength
56
57
  @mutex.synchronize do
57
- Fiber.new do
58
+ fiber = Fiber.new do
58
59
  @handlers[event.to_s].each do |callback|
59
60
  begin
60
61
  callback.call(payload)
61
62
  rescue => e
62
- handle_exception(e, {
63
- :context => "sidekiq:throttled"
64
- })
63
+ handle_exception(e, :context => "sidekiq:throttled")
65
64
  end
66
65
  end
67
- end.resume
66
+ end
67
+
68
+ fiber.resume
68
69
  end
69
70
  end
70
71
  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
@@ -2,6 +2,7 @@
2
2
 
3
3
  # internal
4
4
  require "sidekiq/throttled/errors"
5
+ require "sidekiq/throttled/strategy_collection"
5
6
  require "sidekiq/throttled/strategy/concurrency"
6
7
  require "sidekiq/throttled/strategy/threshold"
7
8
 
@@ -19,28 +20,31 @@ module Sidekiq
19
20
  # @return [Strategy::Threshold, nil]
20
21
  attr_reader :threshold
21
22
 
23
+ # @!attribute [r] observer
24
+ # @return [Proc, nil]
25
+ attr_reader :observer
26
+
22
27
  # @param [#to_s] name
23
28
  # @param [Hash] concurrency Concurrency options.
24
29
  # See keyword args of {Strategy::Concurrency#initialize} for details.
25
30
  # @param [Hash] threshold Threshold options.
26
31
  # See keyword args of {Strategy::Threshold#initialize} for details.
27
32
  # @param [#call] key_suffix Dynamic key suffix generator.
28
- def initialize(name, concurrency: nil, threshold: nil, key_suffix: nil)
29
- key = "throttled:#{name}"
33
+ # @param [#call] observer Process called after throttled.
34
+ def initialize(name, concurrency: nil, threshold: nil, key_suffix: nil, observer: nil) # rubocop:disable Metrics/MethodLength
35
+ @observer = observer
30
36
 
31
- @concurrency =
32
- if concurrency
33
- concurrency[:key_suffix] ||= key_suffix
34
- Concurrency.new(key, **concurrency)
35
- end
37
+ @concurrency = StrategyCollection.new(concurrency,
38
+ :strategy => Concurrency,
39
+ :name => name,
40
+ :key_suffix => key_suffix)
36
41
 
37
- @threshold =
38
- if threshold
39
- threshold[:key_suffix] ||= key_suffix
40
- Threshold.new(key, **threshold)
41
- end
42
+ @threshold = StrategyCollection.new(threshold,
43
+ :strategy => Threshold,
44
+ :name => name,
45
+ :key_suffix => key_suffix)
42
46
 
43
- return if @concurrency || @threshold
47
+ return if @concurrency.any? || @threshold.any?
44
48
 
45
49
  raise ArgumentError, "Neither :concurrency nor :threshold given"
46
50
  end
@@ -55,9 +59,14 @@ module Sidekiq
55
59
 
56
60
  # @return [Boolean] whenever job is throttled or not.
57
61
  def throttled?(jid, *job_args)
58
- return true if @concurrency&.throttled?(jid, *job_args)
62
+ if @concurrency&.throttled?(jid, *job_args)
63
+ @observer&.call(:concurrency, *job_args)
64
+ return true
65
+ end
59
66
 
60
67
  if @threshold&.throttled?(*job_args)
68
+ @observer&.call(:threshold, *job_args)
69
+
61
70
  finalize!(jid, *job_args)
62
71
  return true
63
72
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # internal
4
+ module Sidekiq
5
+ module Throttled
6
+ # Collection which transparently group several meta-strategies of one kind
7
+ #
8
+ # @private
9
+ class StrategyCollection
10
+ include Enumerable
11
+
12
+ attr_reader :strategies
13
+
14
+ # @param [Hash, Array, nil] strategies Concurrency or Threshold options
15
+ # or array of options.
16
+ # See keyword args of {Strategy::Concurrency#initialize} for details.
17
+ # See keyword args of {Strategy::Threshold#initialize} for details.
18
+ # @param [Class] strategy class of strategy: Concurrency or Threshold
19
+ # @param [#to_s] name
20
+ # @param [#call] key_suffix Dynamic key suffix generator.
21
+ def initialize(strategies, strategy:, name:, key_suffix:)
22
+ strategies = (strategies.is_a?(Hash) ? [strategies] : Array(strategies))
23
+ @strategies = strategies.map do |options|
24
+ make_strategy(strategy, name, key_suffix, options)
25
+ end
26
+ end
27
+
28
+ # @param [#call] block
29
+ # Iterates each strategy in collection
30
+ def each(&block)
31
+ @strategies.each(&block)
32
+ end
33
+
34
+ # @return [Boolean] whenever any strategy in collection has dynamic config
35
+ def dynamic?
36
+ any?(&:dynamic?)
37
+ end
38
+
39
+ # @return [Boolean] whenever job is throttled or not
40
+ # by any strategy in collection.
41
+ def throttled?(*args)
42
+ any? { |s| s.throttled?(*args) }
43
+ end
44
+
45
+ # Marks job as being processed.
46
+ # @return [void]
47
+ def finalize!(*args)
48
+ each { |c| c.finalize!(*args) }
49
+ end
50
+
51
+ # Resets count of jobs of all avaliable strategies
52
+ # @return [void]
53
+ def reset!
54
+ each(&:reset!)
55
+ end
56
+
57
+ private
58
+
59
+ # @return [Base, nil]
60
+ def make_strategy(strategy, name, key_suffix, options)
61
+ return unless options
62
+
63
+ strategy.new("throttled:#{name}", {
64
+ :key_suffix => key_suffix,
65
+ **options
66
+ })
67
+ end
68
+ end
69
+ end
70
+ end
@@ -9,7 +9,7 @@ module Sidekiq
9
9
  # @param name [#to_s] Constant name
10
10
  # @return [Object, nil] Resolved constant or nil if failed.
11
11
  def constantize(name)
12
- name.to_s.sub(/^::/, "").split("::").inject(Object, &:const_get)
12
+ name.to_s.sub(%r{^::}, "").split("::").inject(Object, &:const_get)
13
13
  rescue NameError
14
14
  Sidekiq.logger.warn { "Failed to constantize: #{name}" }
15
15
  nil
@@ -3,6 +3,6 @@
3
3
  module Sidekiq
4
4
  module Throttled
5
5
  # Gem version
6
- VERSION = "0.10.0"
6
+ VERSION = "0.14.1"
7
7
  end
8
8
  end
@@ -14,9 +14,7 @@ module Sidekiq
14
14
 
15
15
  # @param [Strategy::Concurrency, Strategy::Threshold] strategy
16
16
  def initialize(strategy)
17
- if strategy&.dynamic?
18
- raise ArgumentError, "Can't handle dynamic strategies"
19
- end
17
+ raise ArgumentError, "Can't handle dynamic strategies" if strategy&.dynamic?
20
18
 
21
19
  @strategy = strategy
22
20
  end
@@ -27,9 +25,7 @@ module Sidekiq
27
25
 
28
26
  html = humanize_integer(@strategy.limit) << " jobs"
29
27
 
30
- if @strategy.respond_to? :period
31
- html << " per " << humanize_duration(@strategy.period)
32
- end
28
+ html << " per " << humanize_duration(@strategy.period) if @strategy.respond_to?(:period)
33
29
 
34
30
  html << "<br />" << colorize_count(@strategy.count, @strategy.limit)
35
31
  end
@@ -4,14 +4,15 @@ module Sidekiq
4
4
  module Throttled
5
5
  module Web
6
6
  module SummaryFix
7
- JAVASCRIPT = [File.read(__FILE__.sub(/\.rb$/, ".js")).freeze].freeze
7
+ JAVASCRIPT = [File.read(File.expand_path("summary_fix.js", __dir__)).freeze].freeze
8
8
  HEADERS = { "Content-Type" => "application/javascript" }.freeze
9
9
 
10
10
  class << self
11
11
  attr_accessor :enabled
12
12
 
13
13
  def apply!(app)
14
- Sidekiq::WebAction.send(:prepend, SummaryFix)
14
+ Sidekiq::WebAction.prepend SummaryFix
15
+
15
16
  app.get("/throttled/summary_fix") do
16
17
  [200, HEADERS.dup, JAVASCRIPT.dup]
17
18
  end
@@ -14,10 +14,14 @@
14
14
  <tr>
15
15
  <td style="vertical-align:middle;"><%= name %></td>
16
16
  <td style="vertical-align:middle;text-align:center;">
17
- <%= Sidekiq::Throttled::Web::Stats.new(strategy.concurrency).to_html %>
17
+ <% strategy.concurrency.each do |concurrency| %>
18
+ <%= Sidekiq::Throttled::Web::Stats.new(concurrency).to_html %>
19
+ <% end %>
18
20
  </td>
19
21
  <td style="vertical-align:middle;text-align:center;">
20
- <%= Sidekiq::Throttled::Web::Stats.new(strategy.threshold).to_html %>
22
+ <% strategy.threshold.each do |threshold| %>
23
+ <%= Sidekiq::Throttled::Web::Stats.new(threshold).to_html %>
24
+ <% end %>
21
25
  </td>
22
26
  <td style="vertical-align:middle;text-align:center;">
23
27
  <form action="<%= root_path %>throttled/<%= CGI.escape name %>/reset" method="post">
@@ -57,7 +57,7 @@ module Sidekiq
57
57
  end
58
58
 
59
59
  # rubocop:disable Metrics/AbcSize
60
- def register_enhanced_queues_tab(app)
60
+ def register_enhanced_queues_tab(app) # rubocop:disable Metrics/MethodLength
61
61
  pauser = QueuesPauser.instance
62
62
 
63
63
  app.get("/enhanced-queues") do
@@ -77,7 +77,7 @@ module Sidekiq
77
77
  Registry.add(self, **kwargs)
78
78
  end
79
79
 
80
- # Adds current worker to preconfigured throtttling strtegy. Allows
80
+ # Adds current worker to preconfigured throttling strategy. Allows
81
81
  # sharing same pool for multiple workers.
82
82
  #
83
83
  # First of all we need to create shared throttling strategy:
@@ -85,7 +85,7 @@ module Sidekiq
85
85
  # # Create google_api throttling strategy
86
86
  # Sidekiq::Throttled::Registry.add(:google_api, {
87
87
  # :threshold => { :limit => 123, :period => 1.hour },
88
- # :concurrency => { :limit => 123 }
88
+ # :concurrency => { :limit => 10 }
89
89
  # })
90
90
  #
91
91
  # Now we can assign it to our workers: