sidekiq 5.2.9 → 6.4.1

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