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