sidekiq 5.0.0 → 6.0.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 (79) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +61 -0
  3. data/.github/issue_template.md +3 -1
  4. data/.gitignore +1 -1
  5. data/.standard.yml +20 -0
  6. data/6.0-Upgrade.md +70 -0
  7. data/COMM-LICENSE +12 -10
  8. data/Changes.md +169 -1
  9. data/Ent-2.0-Upgrade.md +37 -0
  10. data/Ent-Changes.md +76 -0
  11. data/Gemfile +16 -21
  12. data/Gemfile.lock +196 -0
  13. data/LICENSE +1 -1
  14. data/Pro-4.0-Upgrade.md +35 -0
  15. data/Pro-5.0-Upgrade.md +25 -0
  16. data/Pro-Changes.md +137 -1
  17. data/README.md +18 -30
  18. data/Rakefile +6 -8
  19. data/bin/sidekiqload +28 -24
  20. data/bin/sidekiqmon +9 -0
  21. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +1 -1
  22. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  23. data/lib/generators/sidekiq/worker_generator.rb +12 -14
  24. data/lib/sidekiq.rb +69 -49
  25. data/lib/sidekiq/api.rb +216 -160
  26. data/lib/sidekiq/cli.rb +174 -207
  27. data/lib/sidekiq/client.rb +55 -51
  28. data/lib/sidekiq/delay.rb +24 -4
  29. data/lib/sidekiq/exception_handler.rb +12 -16
  30. data/lib/sidekiq/extensions/action_mailer.rb +10 -20
  31. data/lib/sidekiq/extensions/active_record.rb +9 -7
  32. data/lib/sidekiq/extensions/class_methods.rb +9 -7
  33. data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
  34. data/lib/sidekiq/fetch.rb +5 -6
  35. data/lib/sidekiq/job_logger.rb +42 -14
  36. data/lib/sidekiq/job_retry.rb +71 -57
  37. data/lib/sidekiq/launcher.rb +74 -60
  38. data/lib/sidekiq/logger.rb +69 -0
  39. data/lib/sidekiq/manager.rb +12 -15
  40. data/lib/sidekiq/middleware/chain.rb +3 -2
  41. data/lib/sidekiq/middleware/i18n.rb +5 -7
  42. data/lib/sidekiq/monitor.rb +148 -0
  43. data/lib/sidekiq/paginator.rb +11 -12
  44. data/lib/sidekiq/processor.rb +126 -82
  45. data/lib/sidekiq/rails.rb +24 -32
  46. data/lib/sidekiq/redis_connection.rb +46 -14
  47. data/lib/sidekiq/scheduled.rb +50 -25
  48. data/lib/sidekiq/testing.rb +35 -27
  49. data/lib/sidekiq/testing/inline.rb +2 -1
  50. data/lib/sidekiq/util.rb +20 -14
  51. data/lib/sidekiq/version.rb +2 -1
  52. data/lib/sidekiq/web.rb +45 -53
  53. data/lib/sidekiq/web/action.rb +14 -10
  54. data/lib/sidekiq/web/application.rb +83 -58
  55. data/lib/sidekiq/web/helpers.rb +105 -67
  56. data/lib/sidekiq/web/router.rb +18 -15
  57. data/lib/sidekiq/worker.rb +144 -41
  58. data/sidekiq.gemspec +16 -27
  59. data/web/assets/javascripts/application.js +0 -0
  60. data/web/assets/javascripts/dashboard.js +21 -23
  61. data/web/assets/stylesheets/application.css +35 -2
  62. data/web/assets/stylesheets/bootstrap.css +2 -2
  63. data/web/locales/ar.yml +1 -0
  64. data/web/locales/en.yml +2 -0
  65. data/web/locales/es.yml +4 -3
  66. data/web/locales/ja.yml +7 -4
  67. data/web/views/_footer.erb +4 -1
  68. data/web/views/_nav.erb +3 -17
  69. data/web/views/busy.erb +5 -1
  70. data/web/views/layout.erb +1 -1
  71. data/web/views/queue.erb +1 -0
  72. data/web/views/queues.erb +2 -0
  73. data/web/views/retries.erb +4 -0
  74. metadata +25 -171
  75. data/.travis.yml +0 -18
  76. data/bin/sidekiqctl +0 -99
  77. data/lib/sidekiq/core_ext.rb +0 -119
  78. data/lib/sidekiq/logging.rb +0 -106
  79. data/lib/sidekiq/middleware/server/active_record.rb +0 -22
@@ -1,46 +1,29 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
2
+
3
3
  $stdout.sync = true
4
4
 
5
- require 'yaml'
6
- require 'singleton'
7
- require 'optparse'
8
- require 'erb'
9
- require 'fileutils'
5
+ require "yaml"
6
+ require "singleton"
7
+ require "optparse"
8
+ require "erb"
9
+ require "fileutils"
10
10
 
11
- require 'sidekiq'
12
- require 'sidekiq/util'
11
+ require "sidekiq"
12
+ require "sidekiq/launcher"
13
+ require "sidekiq/util"
13
14
 
14
15
  module Sidekiq
15
16
  class CLI
16
17
  include Util
17
18
  include Singleton unless $TESTING
18
19
 
19
- PROCTITLES = [
20
- proc { 'sidekiq'.freeze },
21
- proc { Sidekiq::VERSION },
22
- proc { |me, data| data['tag'] },
23
- proc { |me, data| "[#{Processor::WORKER_STATE.size} of #{data['concurrency']} busy]" },
24
- proc { |me, data| "stopping" if me.stopping? },
25
- ]
26
-
27
- # Used for CLI testing
28
- attr_accessor :code
29
20
  attr_accessor :launcher
30
21
  attr_accessor :environment
31
22
 
32
- def initialize
33
- @code = nil
34
- end
35
-
36
- def parse(args=ARGV)
37
- @code = nil
38
-
23
+ def parse(args = ARGV)
39
24
  setup_options(args)
40
25
  initialize_logger
41
26
  validate!
42
- daemonize
43
- write_pid
44
27
  end
45
28
 
46
29
  def jruby?
@@ -52,24 +35,18 @@ module Sidekiq
52
35
  # test coverage of Sidekiq::CLI are welcomed.
53
36
  def run
54
37
  boot_system
55
- print_banner
56
-
57
- self_read, self_write = IO.pipe
58
- sigs = %w(INT TERM TTIN TSTP)
59
- # USR1 and USR2 don't work on the JVM
60
- if !jruby?
61
- sigs << 'USR1'
62
- sigs << 'USR2'
38
+ if environment == "development" && $stdout.tty? && Sidekiq.log_formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
39
+ print_banner
63
40
  end
64
41
 
42
+ self_read, self_write = IO.pipe
43
+ sigs = %w[INT TERM TTIN TSTP]
65
44
  sigs.each do |sig|
66
- begin
67
- trap sig do
68
- self_write.puts(sig)
69
- end
70
- rescue ArgumentError
71
- puts "Signal #{sig} not supported"
45
+ trap sig do
46
+ self_write.write("#{sig}\n")
72
47
  end
48
+ rescue ArgumentError
49
+ puts "Signal #{sig} not supported"
73
50
  end
74
51
 
75
52
  logger.info "Running in #{RUBY_DESCRIPTION}"
@@ -78,153 +55,180 @@ module Sidekiq
78
55
 
79
56
  # touch the connection pool so it is created before we
80
57
  # fire startup and start multithreading.
81
- ver = Sidekiq.redis_info['redis_version']
82
- raise "You are using Redis v#{ver}, Sidekiq requires Redis v2.8.0 or greater" if ver < '2.8'
58
+ ver = Sidekiq.redis_info["redis_version"]
59
+ raise "You are using Redis v#{ver}, Sidekiq requires Redis v4.0.0 or greater" if ver < "4"
60
+
61
+ # Since the user can pass us a connection pool explicitly in the initializer, we
62
+ # need to verify the size is large enough or else Sidekiq's performance is dramatically slowed.
63
+ cursize = Sidekiq.redis_pool.size
64
+ needed = Sidekiq.options[:concurrency] + 2
65
+ raise "Your pool of #{cursize} Redis connections is too small, please increase the size to at least #{needed}" if cursize < needed
66
+
67
+ # cache process identity
68
+ Sidekiq.options[:identity] = identity
83
69
 
84
70
  # Touch middleware so it isn't lazy loaded by multiple threads, #3043
85
71
  Sidekiq.server_middleware
86
72
 
87
73
  # Before this point, the process is initializing with just the main thread.
88
74
  # Starting here the process will now have multiple threads running.
89
- fire_event(:startup)
75
+ fire_event(:startup, reverse: false, reraise: true)
76
+
77
+ logger.debug { "Client Middleware: #{Sidekiq.client_middleware.map(&:klass).join(", ")}" }
78
+ logger.debug { "Server Middleware: #{Sidekiq.server_middleware.map(&:klass).join(", ")}" }
90
79
 
91
- logger.debug { "Client Middleware: #{Sidekiq.client_middleware.map(&:klass).join(', ')}" }
92
- logger.debug { "Server Middleware: #{Sidekiq.server_middleware.map(&:klass).join(', ')}" }
80
+ launch(self_read)
81
+ end
93
82
 
94
- if !options[:daemon]
95
- logger.info 'Starting processing, hit Ctrl-C to stop'
83
+ def launch(self_read)
84
+ if environment == "development" && $stdout.tty?
85
+ logger.info "Starting processing, hit Ctrl-C to stop"
96
86
  end
97
87
 
98
- require 'sidekiq/launcher'
99
88
  @launcher = Sidekiq::Launcher.new(options)
100
89
 
101
90
  begin
102
91
  launcher.run
103
92
 
104
- while readable_io = IO.select([self_read])
93
+ while (readable_io = IO.select([self_read]))
105
94
  signal = readable_io.first[0].gets.strip
106
95
  handle_signal(signal)
107
96
  end
108
97
  rescue Interrupt
109
- logger.info 'Shutting down'
98
+ logger.info "Shutting down"
110
99
  launcher.stop
111
- # Explicitly exit so busy Processor threads can't block
112
- # process shutdown.
113
100
  logger.info "Bye!"
101
+
102
+ # Explicitly exit so busy Processor threads won't block process shutdown.
103
+ #
104
+ # NB: slow at_exit handlers will prevent a timely exit if they take
105
+ # a while to run. If Sidekiq is getting here but the process isn't exiting,
106
+ # use the TTIN signal to determine where things are stuck.
114
107
  exit(0)
115
108
  end
116
109
  end
117
110
 
111
+ def self.w
112
+ "\e[37m"
113
+ end
114
+
115
+ def self.r
116
+ "\e[31m"
117
+ end
118
+
119
+ def self.b
120
+ "\e[30m"
121
+ end
122
+
123
+ def self.reset
124
+ "\e[0m"
125
+ end
126
+
118
127
  def self.banner
119
- %q{
120
- m,
121
- `$b
122
- .ss, $$: .,d$
123
- `$$P,d$P' .,md$P"'
124
- ,$$$$$bmmd$$$P^'
125
- .d$$$$$$$$$$P'
126
- $$^' `"^$$$' ____ _ _ _ _
127
- $: ,$$: / ___|(_) __| | ___| | _(_) __ _
128
- `b :$$ \___ \| |/ _` |/ _ \ |/ / |/ _` |
129
- $$: ___) | | (_| | __/ <| | (_| |
130
- $$ |____/|_|\__,_|\___|_|\_\_|\__, |
131
- .d$$ |_|
132
- }
128
+ %{
129
+ #{w} m,
130
+ #{w} `$b
131
+ #{w} .ss, $$: .,d$
132
+ #{w} `$$P,d$P' .,md$P"'
133
+ #{w} ,$$$$$b#{b}/#{w}md$$$P^'
134
+ #{w} .d$$$$$$#{b}/#{w}$$$P'
135
+ #{w} $$^' `"#{b}/#{w}$$$' #{r}____ _ _ _ _
136
+ #{w} $: ,$$: #{r} / ___|(_) __| | ___| | _(_) __ _
137
+ #{w} `b :$$ #{r} \\___ \\| |/ _` |/ _ \\ |/ / |/ _` |
138
+ #{w} $$: #{r} ___) | | (_| | __/ <| | (_| |
139
+ #{w} $$ #{r}|____/|_|\\__,_|\\___|_|\\_\\_|\\__, |
140
+ #{w} .d$$ #{r} |_|
141
+ #{reset}}
133
142
  end
134
143
 
135
- def handle_signal(sig)
136
- Sidekiq.logger.debug "Got #{sig} signal"
137
- case sig
138
- when 'INT'
139
- # Handle Ctrl-C in JRuby like MRI
140
- # http://jira.codehaus.org/browse/JRUBY-4637
141
- raise Interrupt
142
- when 'TERM'
143
- # Heroku sends TERM and then waits 10 seconds for process to exit.
144
- raise Interrupt
145
- when 'USR1'
146
- Sidekiq.logger.info "Received USR1, no longer accepting new work"
147
- launcher.quiet
148
- when 'TSTP'
149
- # USR1 is not available on JVM, allow TSTP as an alternate signal
144
+ SIGNAL_HANDLERS = {
145
+ # Ctrl-C in terminal
146
+ "INT" => ->(cli) { raise Interrupt },
147
+ # TERM is the signal that Sidekiq must exit.
148
+ # Heroku sends TERM and then waits 30 seconds for process to exit.
149
+ "TERM" => ->(cli) { raise Interrupt },
150
+ "TSTP" => ->(cli) {
150
151
  Sidekiq.logger.info "Received TSTP, no longer accepting new work"
151
- launcher.quiet
152
- when 'USR2'
153
- if Sidekiq.options[:logfile]
154
- Sidekiq.logger.info "Received USR2, reopening log file"
155
- Sidekiq::Logging.reopen_logs
156
- end
157
- when 'TTIN'
152
+ cli.launcher.quiet
153
+ },
154
+ "TTIN" => ->(cli) {
158
155
  Thread.list.each do |thread|
159
- Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['sidekiq_label']}"
156
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
160
157
  if thread.backtrace
161
158
  Sidekiq.logger.warn thread.backtrace.join("\n")
162
159
  else
163
160
  Sidekiq.logger.warn "<no backtrace available>"
164
161
  end
165
162
  end
163
+ },
164
+ }
165
+
166
+ def handle_signal(sig)
167
+ Sidekiq.logger.debug "Got #{sig} signal"
168
+ handy = SIGNAL_HANDLERS[sig]
169
+ if handy
170
+ handy.call(self)
171
+ else
172
+ Sidekiq.logger.info { "No signal handler for #{sig}" }
166
173
  end
167
174
  end
168
175
 
169
176
  private
170
177
 
171
178
  def print_banner
172
- # Print logo and banner for development
173
- if environment == 'development' && $stdout.tty?
174
- puts "\e[#{31}m"
175
- puts Sidekiq::CLI.banner
176
- puts "\e[0m"
177
- end
179
+ puts "\e[31m"
180
+ puts Sidekiq::CLI.banner
181
+ puts "\e[0m"
178
182
  end
179
183
 
180
- def daemonize
181
- return unless options[:daemon]
182
-
183
- raise ArgumentError, "You really should set a logfile if you're going to daemonize" unless options[:logfile]
184
- files_to_reopen = []
185
- ObjectSpace.each_object(File) do |file|
186
- files_to_reopen << file unless file.closed?
187
- end
188
-
189
- ::Process.daemon(true, true)
190
-
191
- files_to_reopen.each do |file|
192
- begin
193
- file.reopen file.path, "a+"
194
- file.sync = true
195
- rescue ::Exception
196
- end
197
- end
198
-
199
- [$stdout, $stderr].each do |io|
200
- File.open(options[:logfile], 'ab') do |f|
201
- io.reopen(f)
202
- end
203
- io.sync = true
204
- end
205
- $stdin.reopen('/dev/null')
206
-
207
- initialize_logger
184
+ def set_environment(cli_env)
185
+ @environment = cli_env || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
208
186
  end
209
187
 
210
- def set_environment(cli_env)
211
- @environment = cli_env || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
188
+ def symbolize_keys_deep!(hash)
189
+ hash.keys.each do |k|
190
+ symkey = k.respond_to?(:to_sym) ? k.to_sym : k
191
+ hash[symkey] = hash.delete k
192
+ symbolize_keys_deep! hash[symkey] if hash[symkey].is_a? Hash
193
+ end
212
194
  end
213
195
 
214
196
  alias_method :die, :exit
215
197
  alias_method :☠, :exit
216
198
 
217
199
  def setup_options(args)
200
+ # parse CLI options
218
201
  opts = parse_options(args)
202
+
219
203
  set_environment opts[:environment]
220
204
 
221
- cfile = opts[:config_file]
222
- opts = parse_config(cfile).merge(opts) if cfile
205
+ # check config file presence
206
+ if opts[:config_file]
207
+ if opts[:config_file] && !File.exist?(opts[:config_file])
208
+ raise ArgumentError, "No such file #{opts[:config_file]}"
209
+ end
210
+ else
211
+ config_dir = if File.directory?(opts[:require].to_s)
212
+ File.join(opts[:require], "config")
213
+ else
214
+ File.join(options[:require], "config")
215
+ end
216
+
217
+ %w[sidekiq.yml sidekiq.yml.erb].each do |config_file|
218
+ path = File.join(config_dir, config_file)
219
+ opts[:config_file] ||= path if File.exist?(path)
220
+ end
221
+ end
222
+
223
+ # parse config file options
224
+ opts = parse_config(opts[:config_file]).merge(opts) if opts[:config_file]
223
225
 
226
+ # set defaults
227
+ opts[:queues] = Array(opts[:queues]) << "default" if opts[:queues].nil? || opts[:queues].empty?
224
228
  opts[:strict] = true if opts[:strict].nil?
225
- opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if !opts[:concurrency] && ENV["RAILS_MAX_THREADS"]
226
- opts[:identity] = identity
229
+ opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if opts[:concurrency].nil? && ENV["RAILS_MAX_THREADS"]
227
230
 
231
+ # merge with defaults
228
232
  options.merge!(opts)
229
233
  end
230
234
 
@@ -233,41 +237,28 @@ module Sidekiq
233
237
  end
234
238
 
235
239
  def boot_system
236
- ENV['RACK_ENV'] = ENV['RAILS_ENV'] = environment
237
-
238
- raise ArgumentError, "#{options[:require]} does not exist" unless File.exist?(options[:require])
240
+ ENV["RACK_ENV"] = ENV["RAILS_ENV"] = environment
239
241
 
240
242
  if File.directory?(options[:require])
241
- require 'rails'
242
- if ::Rails::VERSION::MAJOR < 4
243
+ require "rails"
244
+ if ::Rails::VERSION::MAJOR < 5
243
245
  raise "Sidekiq no longer supports this version of Rails"
244
- elsif ::Rails::VERSION::MAJOR == 4
245
- # Painful contortions, see 1791 for discussion
246
- # No autoloading, we want to force eager load for everything.
247
- require File.expand_path("#{options[:require]}/config/application.rb")
248
- ::Rails::Application.initializer "sidekiq.eager_load" do
249
- ::Rails.application.config.eager_load = true
250
- end
251
- require 'sidekiq/rails'
252
- require File.expand_path("#{options[:require]}/config/environment.rb")
253
246
  else
254
- require 'sidekiq/rails'
247
+ require "sidekiq/rails"
255
248
  require File.expand_path("#{options[:require]}/config/environment.rb")
256
249
  end
257
250
  options[:tag] ||= default_tag
258
251
  else
259
- not_required_message = "#{options[:require]} was not required, you should use an explicit path: " +
260
- "./#{options[:require]} or /path/to/#{options[:require]}"
261
-
262
- require(options[:require]) || raise(ArgumentError, not_required_message)
252
+ require options[:require]
263
253
  end
264
254
  end
265
255
 
266
256
  def default_tag
267
257
  dir = ::Rails.root
268
258
  name = File.basename(dir)
269
- if name.to_i != 0 && prevdir = File.dirname(dir) # Capistrano release directory?
270
- if File.basename(prevdir) == 'releases'
259
+ prevdir = File.dirname(dir) # Capistrano release directory?
260
+ if name.to_i != 0 && prevdir
261
+ if File.basename(prevdir) == "releases"
271
262
  return File.basename(File.dirname(prevdir))
272
263
  end
273
264
  end
@@ -275,12 +266,10 @@ module Sidekiq
275
266
  end
276
267
 
277
268
  def validate!
278
- options[:queues] << 'default' if options[:queues].empty?
279
-
280
269
  if !File.exist?(options[:require]) ||
281
- (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
270
+ (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
282
271
  logger.info "=================================================================="
283
- logger.info " Please point sidekiq to a Rails 3/4 application or a Ruby file "
272
+ logger.info " Please point Sidekiq to a Rails application or a Ruby file "
284
273
  logger.info " to load your worker classes with -r [DIR|FILE]."
285
274
  logger.info "=================================================================="
286
275
  logger.info @parser
@@ -288,44 +277,40 @@ module Sidekiq
288
277
  end
289
278
 
290
279
  [:concurrency, :timeout].each do |opt|
291
- raise ArgumentError, "#{opt}: #{options[opt]} is not a valid value" if options.has_key?(opt) && options[opt].to_i <= 0
280
+ raise ArgumentError, "#{opt}: #{options[opt]} is not a valid value" if options.key?(opt) && options[opt].to_i <= 0
292
281
  end
293
282
  end
294
283
 
295
284
  def parse_options(argv)
296
285
  opts = {}
297
286
 
298
- @parser = OptionParser.new do |o|
299
- o.on '-c', '--concurrency INT', "processor threads to use" do |arg|
287
+ @parser = OptionParser.new { |o|
288
+ o.on "-c", "--concurrency INT", "processor threads to use" do |arg|
300
289
  opts[:concurrency] = Integer(arg)
301
290
  end
302
291
 
303
- o.on '-d', '--daemon', "Daemonize process" do |arg|
304
- opts[:daemon] = arg
292
+ o.on "-d", "--daemon", "Daemonize process" do |arg|
293
+ puts "ERROR: Daemonization mode was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
305
294
  end
306
295
 
307
- o.on '-e', '--environment ENV', "Application environment" do |arg|
296
+ o.on "-e", "--environment ENV", "Application environment" do |arg|
308
297
  opts[:environment] = arg
309
298
  end
310
299
 
311
- o.on '-g', '--tag TAG', "Process tag for procline" do |arg|
300
+ o.on "-g", "--tag TAG", "Process tag for procline" do |arg|
312
301
  opts[:tag] = arg
313
302
  end
314
303
 
315
- o.on '-i', '--index INT', "unique process index on this machine" do |arg|
316
- opts[:index] = Integer(arg.match(/\d+/)[0])
317
- end
318
-
319
304
  o.on "-q", "--queue QUEUE[,WEIGHT]", "Queues to process with optional weights" do |arg|
320
305
  queue, weight = arg.split(",")
321
306
  parse_queue opts, queue, weight
322
307
  end
323
308
 
324
- o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
309
+ o.on "-r", "--require [PATH|DIR]", "Location of Rails application with workers or file to require" do |arg|
325
310
  opts[:require] = arg
326
311
  end
327
312
 
328
- o.on '-t', '--timeout NUM', "Shutdown timeout" do |arg|
313
+ o.on "-t", "--timeout NUM", "Shutdown timeout" do |arg|
329
314
  opts[:timeout] = Integer(arg)
330
315
  end
331
316
 
@@ -333,69 +318,51 @@ module Sidekiq
333
318
  opts[:verbose] = arg
334
319
  end
335
320
 
336
- o.on '-C', '--config PATH', "path to YAML config file" do |arg|
321
+ o.on "-C", "--config PATH", "path to YAML config file" do |arg|
337
322
  opts[:config_file] = arg
338
323
  end
339
324
 
340
- o.on '-L', '--logfile PATH', "path to writable logfile" do |arg|
341
- opts[:logfile] = arg
325
+ o.on "-L", "--logfile PATH", "path to writable logfile" do |arg|
326
+ puts "ERROR: Logfile redirection was removed in Sidekiq 6.0, Sidekiq will only log to STDOUT"
342
327
  end
343
328
 
344
- o.on '-P', '--pidfile PATH', "path to pidfile" do |arg|
345
- opts[:pidfile] = arg
329
+ o.on "-P", "--pidfile PATH", "path to pidfile" do |arg|
330
+ puts "ERROR: PID file creation was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
346
331
  end
347
332
 
348
- o.on '-V', '--version', "Print version and exit" do |arg|
333
+ o.on "-V", "--version", "Print version and exit" do |arg|
349
334
  puts "Sidekiq #{Sidekiq::VERSION}"
350
335
  die(0)
351
336
  end
352
- end
337
+ }
353
338
 
354
339
  @parser.banner = "sidekiq [options]"
355
340
  @parser.on_tail "-h", "--help", "Show help" do
356
341
  logger.info @parser
357
342
  die 1
358
343
  end
359
- @parser.parse!(argv)
360
344
 
361
- %w[config/sidekiq.yml config/sidekiq.yml.erb].each do |filename|
362
- opts[:config_file] ||= filename if File.exist?(filename)
363
- end
345
+ @parser.parse!(argv)
364
346
 
365
347
  opts
366
348
  end
367
349
 
368
350
  def initialize_logger
369
- Sidekiq::Logging.initialize_logger(options[:logfile]) if options[:logfile]
370
-
371
351
  Sidekiq.logger.level = ::Logger::DEBUG if options[:verbose]
372
352
  end
373
353
 
374
- def write_pid
375
- if path = options[:pidfile]
376
- pidfile = File.expand_path(path)
377
- File.open(pidfile, 'w') do |f|
378
- f.puts ::Process.pid
379
- end
380
- end
381
- end
354
+ def parse_config(path)
355
+ opts = YAML.load(ERB.new(File.read(path)).result) || {}
382
356
 
383
- def parse_config(cfile)
384
- opts = {}
385
- if File.exist?(cfile)
386
- opts = YAML.load(ERB.new(IO.read(cfile)).result) || opts
387
- opts = opts.merge(opts.delete(environment) || {})
388
- parse_queues(opts, opts.delete(:queues) || [])
357
+ if opts.respond_to? :deep_symbolize_keys!
358
+ opts.deep_symbolize_keys!
389
359
  else
390
- # allow a non-existent config file so Sidekiq
391
- # can be deployed by cap with just the defaults.
392
- end
393
- ns = opts.delete(:namespace)
394
- if ns
395
- # logger hasn't been initialized yet, puts is all we have.
396
- puts("namespace should be set in your ruby initializer, is ignored in config file")
397
- puts("config.redis = { :url => ..., :namespace => '#{ns}' }")
360
+ symbolize_keys_deep!(opts)
398
361
  end
362
+
363
+ opts = opts.merge(opts.delete(environment.to_sym) || {})
364
+ parse_queues(opts, opts.delete(:queues) || [])
365
+
399
366
  opts
400
367
  end
401
368
 
@@ -403,10 +370,10 @@ module Sidekiq
403
370
  queues_and_weights.each { |queue_and_weight| parse_queue(opts, *queue_and_weight) }
404
371
  end
405
372
 
406
- def parse_queue(opts, q, weight=nil)
407
- [weight.to_i, 1].max.times do
408
- (opts[:queues] ||= []) << q
409
- end
373
+ def parse_queue(opts, queue, weight = nil)
374
+ opts[:queues] ||= []
375
+ raise ArgumentError, "queues: #{queue} cannot be defined twice" if opts[:queues].include?(queue)
376
+ [weight.to_i, 1].max.times { opts[:queues] << queue }
410
377
  opts[:strict] = false if weight.to_i > 0
411
378
  end
412
379
  end