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