sidekiq 6.2.2 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +279 -11
  3. data/LICENSE.txt +9 -0
  4. data/README.md +45 -32
  5. data/bin/sidekiq +4 -9
  6. data/bin/sidekiqload +207 -117
  7. data/bin/sidekiqmon +4 -1
  8. data/lib/generators/sidekiq/job_generator.rb +57 -0
  9. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  10. data/lib/generators/sidekiq/templates/{worker_spec.rb.erb → job_spec.rb.erb} +1 -1
  11. data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  12. data/lib/sidekiq/api.rb +331 -187
  13. data/lib/sidekiq/capsule.rb +127 -0
  14. data/lib/sidekiq/cli.rb +94 -81
  15. data/lib/sidekiq/client.rb +100 -96
  16. data/lib/sidekiq/{util.rb → component.rb} +14 -41
  17. data/lib/sidekiq/config.rb +274 -0
  18. data/lib/sidekiq/deploy.rb +62 -0
  19. data/lib/sidekiq/embedded.rb +61 -0
  20. data/lib/sidekiq/fetch.rb +26 -26
  21. data/lib/sidekiq/job.rb +371 -5
  22. data/lib/sidekiq/job_logger.rb +16 -28
  23. data/lib/sidekiq/job_retry.rb +85 -59
  24. data/lib/sidekiq/job_util.rb +105 -0
  25. data/lib/sidekiq/launcher.rb +106 -94
  26. data/lib/sidekiq/logger.rb +9 -44
  27. data/lib/sidekiq/manager.rb +40 -41
  28. data/lib/sidekiq/metrics/query.rb +153 -0
  29. data/lib/sidekiq/metrics/shared.rb +95 -0
  30. data/lib/sidekiq/metrics/tracking.rb +136 -0
  31. data/lib/sidekiq/middleware/chain.rb +96 -51
  32. data/lib/sidekiq/middleware/current_attributes.rb +56 -0
  33. data/lib/sidekiq/middleware/i18n.rb +6 -4
  34. data/lib/sidekiq/middleware/modules.rb +21 -0
  35. data/lib/sidekiq/monitor.rb +17 -4
  36. data/lib/sidekiq/paginator.rb +17 -9
  37. data/lib/sidekiq/processor.rb +60 -60
  38. data/lib/sidekiq/rails.rb +25 -6
  39. data/lib/sidekiq/redis_client_adapter.rb +96 -0
  40. data/lib/sidekiq/redis_connection.rb +17 -88
  41. data/lib/sidekiq/ring_buffer.rb +29 -0
  42. data/lib/sidekiq/scheduled.rb +101 -44
  43. data/lib/sidekiq/testing/inline.rb +4 -4
  44. data/lib/sidekiq/testing.rb +41 -68
  45. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  46. data/lib/sidekiq/version.rb +2 -1
  47. data/lib/sidekiq/web/action.rb +3 -3
  48. data/lib/sidekiq/web/application.rb +47 -13
  49. data/lib/sidekiq/web/csrf_protection.rb +3 -3
  50. data/lib/sidekiq/web/helpers.rb +36 -33
  51. data/lib/sidekiq/web.rb +10 -17
  52. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  53. data/lib/sidekiq.rb +86 -201
  54. data/sidekiq.gemspec +12 -10
  55. data/web/assets/javascripts/application.js +131 -60
  56. data/web/assets/javascripts/base-charts.js +106 -0
  57. data/web/assets/javascripts/chart.min.js +13 -0
  58. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  59. data/web/assets/javascripts/dashboard-charts.js +166 -0
  60. data/web/assets/javascripts/dashboard.js +36 -273
  61. data/web/assets/javascripts/metrics.js +264 -0
  62. data/web/assets/stylesheets/application-dark.css +23 -23
  63. data/web/assets/stylesheets/application-rtl.css +2 -95
  64. data/web/assets/stylesheets/application.css +73 -402
  65. data/web/locales/ar.yml +70 -70
  66. data/web/locales/cs.yml +62 -62
  67. data/web/locales/da.yml +60 -53
  68. data/web/locales/de.yml +65 -65
  69. data/web/locales/el.yml +43 -24
  70. data/web/locales/en.yml +82 -69
  71. data/web/locales/es.yml +68 -68
  72. data/web/locales/fa.yml +65 -65
  73. data/web/locales/fr.yml +81 -67
  74. data/web/locales/gd.yml +99 -0
  75. data/web/locales/he.yml +65 -64
  76. data/web/locales/hi.yml +59 -59
  77. data/web/locales/it.yml +53 -53
  78. data/web/locales/ja.yml +73 -68
  79. data/web/locales/ko.yml +52 -52
  80. data/web/locales/lt.yml +66 -66
  81. data/web/locales/nb.yml +61 -61
  82. data/web/locales/nl.yml +52 -52
  83. data/web/locales/pl.yml +45 -45
  84. data/web/locales/pt-br.yml +63 -55
  85. data/web/locales/pt.yml +51 -51
  86. data/web/locales/ru.yml +67 -66
  87. data/web/locales/sv.yml +53 -53
  88. data/web/locales/ta.yml +60 -60
  89. data/web/locales/uk.yml +62 -61
  90. data/web/locales/ur.yml +64 -64
  91. data/web/locales/vi.yml +67 -67
  92. data/web/locales/zh-cn.yml +43 -16
  93. data/web/locales/zh-tw.yml +42 -8
  94. data/web/views/_footer.erb +6 -3
  95. data/web/views/_job_info.erb +18 -2
  96. data/web/views/_metrics_period_select.erb +12 -0
  97. data/web/views/_nav.erb +1 -1
  98. data/web/views/_paging.erb +2 -0
  99. data/web/views/_poll_link.erb +3 -6
  100. data/web/views/_summary.erb +7 -7
  101. data/web/views/busy.erb +44 -28
  102. data/web/views/dashboard.erb +44 -12
  103. data/web/views/layout.erb +1 -1
  104. data/web/views/metrics.erb +82 -0
  105. data/web/views/metrics_for_job.erb +68 -0
  106. data/web/views/morgue.erb +5 -9
  107. data/web/views/queue.erb +24 -24
  108. data/web/views/queues.erb +4 -2
  109. data/web/views/retries.erb +5 -9
  110. data/web/views/scheduled.erb +12 -13
  111. metadata +62 -31
  112. data/LICENSE +0 -9
  113. data/lib/generators/sidekiq/worker_generator.rb +0 -57
  114. data/lib/sidekiq/delay.rb +0 -41
  115. data/lib/sidekiq/exception_handler.rb +0 -27
  116. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  117. data/lib/sidekiq/extensions/active_record.rb +0 -43
  118. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  119. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  120. data/lib/sidekiq/worker.rb +0 -244
@@ -0,0 +1,127 @@
1
+ require "sidekiq/component"
2
+
3
+ module Sidekiq
4
+ # A Sidekiq::Capsule is the set of resources necessary to
5
+ # process one or more queues with a given concurrency.
6
+ # One "default" Capsule is started but the user may declare additional
7
+ # Capsules in their initializer.
8
+ #
9
+ # This capsule will pull jobs from the "single" queue and process
10
+ # the jobs with one thread, meaning the jobs will be processed serially.
11
+ #
12
+ # Sidekiq.configure_server do |config|
13
+ # config.capsule("single-threaded") do |cap|
14
+ # cap.concurrency = 1
15
+ # cap.queues = %w(single)
16
+ # end
17
+ # end
18
+ class Capsule
19
+ include Sidekiq::Component
20
+
21
+ attr_reader :name
22
+ attr_reader :queues
23
+ attr_accessor :concurrency
24
+ attr_reader :mode
25
+ attr_reader :weights
26
+
27
+ def initialize(name, config)
28
+ @name = name
29
+ @config = config
30
+ @queues = ["default"]
31
+ @weights = {"default" => 0}
32
+ @concurrency = config[:concurrency]
33
+ @mode = :strict
34
+ end
35
+
36
+ def fetcher
37
+ @fetcher ||= begin
38
+ inst = (config[:fetch_class] || Sidekiq::BasicFetch).new(self)
39
+ inst.setup(config[:fetch_setup]) if inst.respond_to?(:setup)
40
+ inst
41
+ end
42
+ end
43
+
44
+ def stop
45
+ fetcher&.bulk_requeue([])
46
+ end
47
+
48
+ # Sidekiq checks queues in three modes:
49
+ # - :strict - all queues have 0 weight and are checked strictly in order
50
+ # - :weighted - queues have arbitrary weight between 1 and N
51
+ # - :random - all queues have weight of 1
52
+ def queues=(val)
53
+ @weights = {}
54
+ @queues = Array(val).each_with_object([]) do |qstr, memo|
55
+ arr = qstr
56
+ arr = qstr.split(",") if qstr.is_a?(String)
57
+ name, weight = arr
58
+ @weights[name] = weight.to_i
59
+ [weight.to_i, 1].max.times do
60
+ memo << name
61
+ end
62
+ end
63
+ @mode = if @weights.values.all?(&:zero?)
64
+ :strict
65
+ elsif @weights.values.all? { |x| x == 1 }
66
+ :random
67
+ else
68
+ :weighted
69
+ end
70
+ end
71
+
72
+ # Allow the middleware to be different per-capsule.
73
+ # Avoid if possible and add middleware globally so all
74
+ # capsules share the same chains. Easier to debug that way.
75
+ def client_middleware
76
+ @client_chain ||= config.client_middleware.copy_for(self)
77
+ yield @client_chain if block_given?
78
+ @client_chain
79
+ end
80
+
81
+ def server_middleware
82
+ @server_chain ||= config.server_middleware.copy_for(self)
83
+ yield @server_chain if block_given?
84
+ @server_chain
85
+ end
86
+
87
+ def redis_pool
88
+ Thread.current[:sidekiq_redis_pool] || local_redis_pool
89
+ end
90
+
91
+ def local_redis_pool
92
+ # connection pool is lazy, it will not create connections unless you actually need them
93
+ # so don't be skimpy!
94
+ @redis ||= config.new_redis_pool(@concurrency, name)
95
+ end
96
+
97
+ def redis
98
+ raise ArgumentError, "requires a block" unless block_given?
99
+ redis_pool.with do |conn|
100
+ retryable = true
101
+ begin
102
+ yield conn
103
+ rescue RedisClientAdapter::BaseError => ex
104
+ # 2550 Failover can cause the server to become a replica, need
105
+ # to disconnect and reopen the socket to get back to the primary.
106
+ # 4495 Use the same logic if we have a "Not enough replicas" error from the primary
107
+ # 4985 Use the same logic when a blocking command is force-unblocked
108
+ # The same retry logic is also used in client.rb
109
+ if retryable && ex.message =~ /READONLY|NOREPLICAS|UNBLOCKED/
110
+ conn.close
111
+ retryable = false
112
+ retry
113
+ end
114
+ raise
115
+ end
116
+ end
117
+ end
118
+
119
+ def lookup(name)
120
+ config.lookup(name)
121
+ end
122
+
123
+ def logger
124
+ config.logger
125
+ end
126
+ end
127
+ end
data/lib/sidekiq/cli.rb CHANGED
@@ -9,18 +9,23 @@ require "erb"
9
9
  require "fileutils"
10
10
 
11
11
  require "sidekiq"
12
+ require "sidekiq/config"
13
+ require "sidekiq/component"
14
+ require "sidekiq/capsule"
12
15
  require "sidekiq/launcher"
13
- require "sidekiq/util"
14
16
 
15
- module Sidekiq
17
+ module Sidekiq # :nodoc:
16
18
  class CLI
17
- include Util
19
+ include Sidekiq::Component
18
20
  include Singleton unless $TESTING
19
21
 
20
22
  attr_accessor :launcher
21
23
  attr_accessor :environment
24
+ attr_accessor :config
25
+
26
+ def parse(args = ARGV.dup)
27
+ @config ||= Sidekiq.default_configuration
22
28
 
23
- def parse(args = ARGV)
24
29
  setup_options(args)
25
30
  initialize_logger
26
31
  validate!
@@ -36,7 +41,7 @@ module Sidekiq
36
41
  def run(boot_app: true)
37
42
  boot_application if boot_app
38
43
 
39
- if environment == "development" && $stdout.tty? && Sidekiq.log_formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
44
+ if environment == "development" && $stdout.tty? && @config.logger.formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
40
45
  print_banner
41
46
  end
42
47
  logger.info "Booted Rails #{::Rails.version} application in #{environment} environment" if rails_app?
@@ -46,7 +51,15 @@ module Sidekiq
46
51
  # USR1 and USR2 don't work on the JVM
47
52
  sigs << "USR2" if Sidekiq.pro? && !jruby?
48
53
  sigs.each do |sig|
49
- trap sig do
54
+ old_handler = Signal.trap(sig) do
55
+ if old_handler.respond_to?(:call)
56
+ begin
57
+ old_handler.call
58
+ rescue Exception => exc
59
+ # signal handlers can't use Logger so puts only
60
+ puts ["Error in #{sig} handler", exc].inspect
61
+ end
62
+ end
50
63
  self_write.puts(sig)
51
64
  end
52
65
  rescue ArgumentError
@@ -59,40 +72,41 @@ module Sidekiq
59
72
 
60
73
  # touch the connection pool so it is created before we
61
74
  # fire startup and start multithreading.
62
- info = Sidekiq.redis_info
63
- ver = info["redis_version"]
64
- raise "You are connecting to Redis v#{ver}, Sidekiq requires Redis v4.0.0 or greater" if ver < "4"
75
+ info = @config.redis_info
76
+ ver = Gem::Version.new(info["redis_version"])
77
+ raise "You are connecting to Redis #{ver}, Sidekiq requires Redis 6.2.0 or greater" if ver < Gem::Version.new("6.2.0")
65
78
 
66
79
  maxmemory_policy = info["maxmemory_policy"]
67
- if maxmemory_policy != "noeviction"
80
+ if maxmemory_policy != "noeviction" && maxmemory_policy != ""
81
+ # Redis Enterprise Cloud returns "" for their policy 😳
68
82
  logger.warn <<~EOM
69
83
 
70
84
 
71
85
  WARNING: Your Redis instance will evict Sidekiq data under heavy load.
72
86
  The 'noeviction' maxmemory policy is recommended (current policy: '#{maxmemory_policy}').
73
- See: https://github.com/mperham/sidekiq/wiki/Using-Redis#memory
87
+ See: https://github.com/sidekiq/sidekiq/wiki/Using-Redis#memory
74
88
 
75
89
  EOM
76
90
  end
77
91
 
78
92
  # Since the user can pass us a connection pool explicitly in the initializer, we
79
93
  # need to verify the size is large enough or else Sidekiq's performance is dramatically slowed.
80
- cursize = Sidekiq.redis_pool.size
81
- needed = Sidekiq.options[:concurrency] + 2
82
- raise "Your pool of #{cursize} Redis connections is too small, please increase the size to at least #{needed}" if cursize < needed
94
+ @config.capsules.each_pair do |name, cap|
95
+ raise ArgumentError, "Pool size too small for #{name}" if cap.redis_pool.size < cap.concurrency
96
+ end
83
97
 
84
98
  # cache process identity
85
- Sidekiq.options[:identity] = identity
99
+ @config[:identity] = identity
86
100
 
87
101
  # Touch middleware so it isn't lazy loaded by multiple threads, #3043
88
- Sidekiq.server_middleware
102
+ @config.server_middleware
89
103
 
90
104
  # Before this point, the process is initializing with just the main thread.
91
105
  # Starting here the process will now have multiple threads running.
92
106
  fire_event(:startup, reverse: false, reraise: true)
93
107
 
94
- logger.debug { "Client Middleware: #{Sidekiq.client_middleware.map(&:klass).join(", ")}" }
95
- logger.debug { "Server Middleware: #{Sidekiq.server_middleware.map(&:klass).join(", ")}" }
108
+ logger.debug { "Client Middleware: #{@config.default_capsule.client_middleware.map(&:klass).join(", ")}" }
109
+ logger.debug { "Server Middleware: #{@config.default_capsule.server_middleware.map(&:klass).join(", ")}" }
96
110
 
97
111
  launch(self_read)
98
112
  end
@@ -102,13 +116,13 @@ module Sidekiq
102
116
  logger.info "Starting processing, hit Ctrl-C to stop"
103
117
  end
104
118
 
105
- @launcher = Sidekiq::Launcher.new(options)
119
+ @launcher = Sidekiq::Launcher.new(@config)
106
120
 
107
121
  begin
108
122
  launcher.run
109
123
 
110
- while (readable_io = IO.select([self_read]))
111
- signal = readable_io.first[0].gets.strip
124
+ while self_read.wait_readable
125
+ signal = self_read.gets.strip
112
126
  handle_signal(signal)
113
127
  end
114
128
  rescue Interrupt
@@ -125,19 +139,34 @@ module Sidekiq
125
139
  end
126
140
  end
127
141
 
128
- def self.w
129
- "\e[37m"
142
+ HOLIDAY_COLORS = {
143
+ # got other color-specific holidays from around the world?
144
+ # https://developer-book.com/post/definitive-guide-for-colored-text-in-terminal/#256-color-escape-codes
145
+ "3-17" => "\e[1;32m", # St. Patrick's Day green
146
+ "10-31" => "\e[38;5;208m" # Halloween orange
147
+ }
148
+
149
+ def self.day
150
+ @@day ||= begin
151
+ t = Date.today
152
+ "#{t.month}-#{t.day}"
153
+ end
130
154
  end
131
155
 
132
156
  def self.r
133
- "\e[31m"
157
+ @@r ||= HOLIDAY_COLORS[day] || "\e[1;31m"
134
158
  end
135
159
 
136
160
  def self.b
137
- "\e[30m"
161
+ @@b ||= HOLIDAY_COLORS[day] || "\e[30m"
162
+ end
163
+
164
+ def self.w
165
+ "\e[1;37m"
138
166
  end
139
167
 
140
168
  def self.reset
169
+ @@b = @@r = @@day = nil
141
170
  "\e[0m"
142
171
  end
143
172
 
@@ -150,7 +179,7 @@ module Sidekiq
150
179
  #{w} ,$$$$$b#{b}/#{w}md$$$P^'
151
180
  #{w} .d$$$$$$#{b}/#{w}$$$P'
152
181
  #{w} $$^' `"#{b}/#{w}$$$' #{r}____ _ _ _ _
153
- #{w} $: ,$$: #{r} / ___|(_) __| | ___| | _(_) __ _
182
+ #{w} $: #{b}'#{w},$$: #{r} / ___|(_) __| | ___| | _(_) __ _
154
183
  #{w} `b :$$ #{r} \\___ \\| |/ _` |/ _ \\ |/ / |/ _` |
155
184
  #{w} $$: #{r} ___) | | (_| | __/ <| | (_| |
156
185
  #{w} $$ #{r}|____/|_|\\__,_|\\___|_|\\_\\_|\\__, |
@@ -165,25 +194,25 @@ module Sidekiq
165
194
  # Heroku sends TERM and then waits 30 seconds for process to exit.
166
195
  "TERM" => ->(cli) { raise Interrupt },
167
196
  "TSTP" => ->(cli) {
168
- Sidekiq.logger.info "Received TSTP, no longer accepting new work"
197
+ cli.logger.info "Received TSTP, no longer accepting new work"
169
198
  cli.launcher.quiet
170
199
  },
171
200
  "TTIN" => ->(cli) {
172
201
  Thread.list.each do |thread|
173
- Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
202
+ cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
174
203
  if thread.backtrace
175
- Sidekiq.logger.warn thread.backtrace.join("\n")
204
+ cli.logger.warn thread.backtrace.join("\n")
176
205
  else
177
- Sidekiq.logger.warn "<no backtrace available>"
206
+ cli.logger.warn "<no backtrace available>"
178
207
  end
179
208
  end
180
209
  }
181
210
  }
182
- UNHANDLED_SIGNAL_HANDLER = ->(cli) { Sidekiq.logger.info "No signal handler registered, ignoring" }
211
+ UNHANDLED_SIGNAL_HANDLER = ->(cli) { cli.logger.info "No signal handler registered, ignoring" }
183
212
  SIGNAL_HANDLERS.default = UNHANDLED_SIGNAL_HANDLER
184
213
 
185
214
  def handle_signal(sig)
186
- Sidekiq.logger.debug "Got #{sig} signal"
215
+ logger.debug "Got #{sig} signal"
187
216
  SIGNAL_HANDLERS[sig].call(self)
188
217
  end
189
218
 
@@ -229,7 +258,7 @@ module Sidekiq
229
258
  config_dir = if File.directory?(opts[:require].to_s)
230
259
  File.join(opts[:require], "config")
231
260
  else
232
- File.join(options[:require], "config")
261
+ File.join(@config[:require], "config")
233
262
  end
234
263
 
235
264
  %w[sidekiq.yml sidekiq.yml.erb].each do |config_file|
@@ -246,27 +275,34 @@ module Sidekiq
246
275
  opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if opts[:concurrency].nil? && ENV["RAILS_MAX_THREADS"]
247
276
 
248
277
  # merge with defaults
249
- options.merge!(opts)
250
- end
278
+ @config.merge!(opts)
251
279
 
252
- def options
253
- Sidekiq.options
280
+ @config.default_capsule.tap do |cap|
281
+ cap.queues = opts[:queues]
282
+ cap.concurrency = opts[:concurrency] || @config[:concurrency]
283
+ end
284
+
285
+ opts[:capsules]&.each do |name, cap_config|
286
+ @config.capsule(name.to_s) do |cap|
287
+ cap.queues = cap_config[:queues]
288
+ cap.concurrency = cap_config[:concurrency]
289
+ end
290
+ end
254
291
  end
255
292
 
256
293
  def boot_application
257
294
  ENV["RACK_ENV"] = ENV["RAILS_ENV"] = environment
258
295
 
259
- if File.directory?(options[:require])
296
+ if File.directory?(@config[:require])
260
297
  require "rails"
261
- if ::Rails::VERSION::MAJOR < 5
262
- raise "Sidekiq no longer supports this version of Rails"
263
- else
264
- require "sidekiq/rails"
265
- require File.expand_path("#{options[:require]}/config/environment.rb")
298
+ if ::Rails::VERSION::MAJOR < 6
299
+ warn "Sidekiq #{Sidekiq::VERSION} only supports Rails 6+"
266
300
  end
267
- options[:tag] ||= default_tag
301
+ require "sidekiq/rails"
302
+ require File.expand_path("#{@config[:require]}/config/environment.rb")
303
+ @config[:tag] ||= default_tag
268
304
  else
269
- require options[:require]
305
+ require @config[:require]
270
306
  end
271
307
  end
272
308
 
@@ -283,18 +319,18 @@ module Sidekiq
283
319
  end
284
320
 
285
321
  def validate!
286
- if !File.exist?(options[:require]) ||
287
- (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
322
+ if !File.exist?(@config[:require]) ||
323
+ (File.directory?(@config[:require]) && !File.exist?("#{@config[:require]}/config/application.rb"))
288
324
  logger.info "=================================================================="
289
325
  logger.info " Please point Sidekiq to a Rails application or a Ruby file "
290
- logger.info " to load your worker classes with -r [DIR|FILE]."
326
+ logger.info " to load your job classes with -r [DIR|FILE]."
291
327
  logger.info "=================================================================="
292
328
  logger.info @parser
293
329
  die(1)
294
330
  end
295
331
 
296
332
  [:concurrency, :timeout].each do |opt|
297
- raise ArgumentError, "#{opt}: #{options[opt]} is not a valid value" if options.key?(opt) && options[opt].to_i <= 0
333
+ raise ArgumentError, "#{opt}: #{@config[opt]} is not a valid value" if @config[opt].to_i <= 0
298
334
  end
299
335
  end
300
336
 
@@ -311,10 +347,6 @@ module Sidekiq
311
347
  opts[:concurrency] = Integer(arg)
312
348
  end
313
349
 
314
- o.on "-d", "--daemon", "Daemonize process" do |arg|
315
- puts "ERROR: Daemonization mode was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
316
- end
317
-
318
350
  o.on "-e", "--environment ENV", "Application environment" do |arg|
319
351
  opts[:environment] = arg
320
352
  end
@@ -324,11 +356,11 @@ module Sidekiq
324
356
  end
325
357
 
326
358
  o.on "-q", "--queue QUEUE[,WEIGHT]", "Queues to process with optional weights" do |arg|
327
- queue, weight = arg.split(",")
328
- parse_queue opts, queue, weight
359
+ opts[:queues] ||= []
360
+ opts[:queues] << arg
329
361
  end
330
362
 
331
- o.on "-r", "--require [PATH|DIR]", "Location of Rails application with workers or file to require" do |arg|
363
+ o.on "-r", "--require [PATH|DIR]", "Location of Rails application with jobs or file to require" do |arg|
332
364
  opts[:require] = arg
333
365
  end
334
366
 
@@ -344,15 +376,7 @@ module Sidekiq
344
376
  opts[:config_file] = arg
345
377
  end
346
378
 
347
- o.on "-L", "--logfile PATH", "path to writable logfile" do |arg|
348
- puts "ERROR: Logfile redirection was removed in Sidekiq 6.0, Sidekiq will only log to STDOUT"
349
- end
350
-
351
- o.on "-P", "--pidfile PATH", "path to pidfile" do |arg|
352
- puts "ERROR: PID file creation was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
353
- end
354
-
355
- o.on "-V", "--version", "Print version and exit" do |arg|
379
+ o.on "-V", "--version", "Print version and exit" do
356
380
  puts "Sidekiq #{Sidekiq::VERSION}"
357
381
  die(0)
358
382
  end
@@ -368,11 +392,13 @@ module Sidekiq
368
392
  end
369
393
 
370
394
  def initialize_logger
371
- Sidekiq.logger.level = ::Logger::DEBUG if options[:verbose]
395
+ @config.logger.level = ::Logger::DEBUG if @config[:verbose]
372
396
  end
373
397
 
374
398
  def parse_config(path)
375
- opts = YAML.load(ERB.new(File.read(path)).result) || {}
399
+ erb = ERB.new(File.read(path), trim_mode: "-")
400
+ erb.filename = File.expand_path(path)
401
+ opts = YAML.safe_load(erb.result, permitted_classes: [Symbol], aliases: true) || {}
376
402
 
377
403
  if opts.respond_to? :deep_symbolize_keys!
378
404
  opts.deep_symbolize_keys!
@@ -383,23 +409,9 @@ module Sidekiq
383
409
  opts = opts.merge(opts.delete(environment.to_sym) || {})
384
410
  opts.delete(:strict)
385
411
 
386
- parse_queues(opts, opts.delete(:queues) || [])
387
-
388
412
  opts
389
413
  end
390
414
 
391
- def parse_queues(opts, queues_and_weights)
392
- queues_and_weights.each { |queue_and_weight| parse_queue(opts, *queue_and_weight) }
393
- end
394
-
395
- def parse_queue(opts, queue, weight = nil)
396
- opts[:queues] ||= []
397
- opts[:strict] = true if opts[:strict].nil?
398
- raise ArgumentError, "queues: #{queue} cannot be defined twice" if opts[:queues].include?(queue)
399
- [weight.to_i, 1].max.times { opts[:queues] << queue }
400
- opts[:strict] = false if weight.to_i > 0
401
- end
402
-
403
415
  def rails_app?
404
416
  defined?(::Rails) && ::Rails.respond_to?(:application)
405
417
  end
@@ -407,3 +419,4 @@ module Sidekiq
407
419
  end
408
420
 
409
421
  require "sidekiq/systemd"
422
+ require "sidekiq/metrics/tracking"