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