sidekiq 6.0.4 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Changes.md +491 -10
- data/LICENSE.txt +9 -0
- data/README.md +47 -38
- data/bin/sidekiq +22 -3
- data/bin/sidekiqload +207 -117
- data/bin/sidekiqmon +4 -1
- 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 +418 -233
- data/lib/sidekiq/capsule.rb +127 -0
- data/lib/sidekiq/cli.rb +122 -86
- data/lib/sidekiq/client.rb +109 -97
- data/lib/sidekiq/{util.rb → component.rb} +14 -13
- data/lib/sidekiq/config.rb +287 -0
- data/lib/sidekiq/deploy.rb +62 -0
- data/lib/sidekiq/embedded.rb +61 -0
- data/lib/sidekiq/fetch.rb +43 -35
- data/lib/sidekiq/{worker.rb → job.rb} +161 -34
- data/lib/sidekiq/job_logger.rb +18 -30
- data/lib/sidekiq/job_retry.rb +102 -63
- data/lib/sidekiq/job_util.rb +107 -0
- data/lib/sidekiq/launcher.rb +180 -88
- data/lib/sidekiq/logger.rb +13 -47
- data/lib/sidekiq/manager.rb +40 -41
- data/lib/sidekiq/metrics/query.rb +155 -0
- data/lib/sidekiq/metrics/shared.rb +95 -0
- data/lib/sidekiq/metrics/tracking.rb +136 -0
- data/lib/sidekiq/middleware/chain.rb +99 -52
- data/lib/sidekiq/middleware/current_attributes.rb +95 -0
- data/lib/sidekiq/middleware/i18n.rb +6 -4
- data/lib/sidekiq/middleware/modules.rb +21 -0
- data/lib/sidekiq/monitor.rb +18 -5
- data/lib/sidekiq/paginator.rb +17 -9
- data/lib/sidekiq/processor.rb +81 -80
- data/lib/sidekiq/rails.rb +37 -21
- data/lib/sidekiq/redis_client_adapter.rb +111 -0
- data/lib/sidekiq/redis_connection.rb +22 -87
- data/lib/sidekiq/ring_buffer.rb +29 -0
- data/lib/sidekiq/scheduled.rb +102 -39
- data/lib/sidekiq/sd_notify.rb +149 -0
- data/lib/sidekiq/systemd.rb +24 -0
- data/lib/sidekiq/testing/inline.rb +4 -4
- data/lib/sidekiq/testing.rb +68 -78
- data/lib/sidekiq/transaction_aware_client.rb +44 -0
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +3 -3
- data/lib/sidekiq/web/application.rb +132 -28
- data/lib/sidekiq/web/csrf_protection.rb +180 -0
- data/lib/sidekiq/web/helpers.rb +93 -65
- data/lib/sidekiq/web/router.rb +6 -5
- data/lib/sidekiq/web.rb +43 -74
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +86 -199
- data/sidekiq.gemspec +17 -8
- data/web/assets/images/apple-touch-icon.png +0 -0
- data/web/assets/javascripts/application.js +146 -61
- data/web/assets/javascripts/base-charts.js +106 -0
- 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-charts.js +182 -0
- data/web/assets/javascripts/dashboard.js +35 -274
- data/web/assets/javascripts/metrics.js +298 -0
- data/web/assets/stylesheets/application-dark.css +146 -124
- data/web/assets/stylesheets/application-rtl.css +2 -95
- data/web/assets/stylesheets/application.css +109 -529
- data/web/locales/ar.yml +71 -65
- data/web/locales/cs.yml +62 -62
- data/web/locales/da.yml +60 -53
- data/web/locales/de.yml +65 -65
- data/web/locales/el.yml +43 -24
- data/web/locales/en.yml +85 -67
- data/web/locales/es.yml +70 -54
- data/web/locales/fa.yml +65 -65
- data/web/locales/fr.yml +83 -62
- data/web/locales/gd.yml +99 -0
- data/web/locales/he.yml +65 -64
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +53 -53
- data/web/locales/ja.yml +75 -65
- data/web/locales/ko.yml +52 -52
- data/web/locales/lt.yml +83 -0
- data/web/locales/nb.yml +61 -61
- data/web/locales/nl.yml +52 -52
- data/web/locales/pl.yml +45 -45
- data/web/locales/pt-br.yml +83 -55
- data/web/locales/pt.yml +51 -51
- data/web/locales/ru.yml +68 -63
- data/web/locales/sv.yml +53 -53
- data/web/locales/ta.yml +60 -60
- data/web/locales/uk.yml +62 -61
- data/web/locales/ur.yml +64 -64
- data/web/locales/vi.yml +83 -0
- data/web/locales/zh-cn.yml +43 -16
- data/web/locales/zh-tw.yml +42 -8
- data/web/views/_footer.erb +6 -3
- data/web/views/_job_info.erb +19 -3
- data/web/views/_metrics_period_select.erb +12 -0
- data/web/views/_nav.erb +1 -1
- data/web/views/_paging.erb +2 -0
- data/web/views/_poll_link.erb +3 -6
- data/web/views/_summary.erb +7 -7
- data/web/views/busy.erb +73 -26
- data/web/views/dashboard.erb +48 -18
- data/web/views/dead.erb +1 -1
- data/web/views/filtering.erb +7 -0
- data/web/views/layout.erb +3 -2
- data/web/views/metrics.erb +91 -0
- data/web/views/metrics_for_job.erb +59 -0
- data/web/views/morgue.erb +11 -15
- data/web/views/queue.erb +25 -25
- data/web/views/queues.erb +13 -7
- data/web/views/retries.erb +12 -16
- data/web/views/retry.erb +1 -1
- data/web/views/scheduled.erb +13 -14
- metadata +65 -56
- data/.circleci/config.yml +0 -82
- data/.github/contributing.md +0 -32
- data/.github/issue_template.md +0 -11
- data/.gitignore +0 -13
- data/.standard.yml +0 -20
- data/3.0-Upgrade.md +0 -70
- data/4.0-Upgrade.md +0 -53
- data/5.0-Upgrade.md +0 -56
- data/6.0-Upgrade.md +0 -72
- data/COMM-LICENSE +0 -97
- data/Ent-2.0-Upgrade.md +0 -37
- data/Ent-Changes.md +0 -256
- data/Gemfile +0 -24
- data/Gemfile.lock +0 -199
- data/LICENSE +0 -9
- 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-5.0-Upgrade.md +0 -25
- data/Pro-Changes.md +0 -776
- data/Rakefile +0 -10
- data/code_of_conduct.md +0 -50
- data/lib/generators/sidekiq/worker_generator.rb +0 -57
- data/lib/sidekiq/delay.rb +0 -41
- data/lib/sidekiq/exception_handler.rb +0 -27
- data/lib/sidekiq/extensions/action_mailer.rb +0 -47
- data/lib/sidekiq/extensions/active_record.rb +0 -42
- data/lib/sidekiq/extensions/class_methods.rb +0 -42
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -31
@@ -0,0 +1,127 @@
|
|
1
|
+
require "sidekiq/component"
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
# A Sidekiq::Capsule is the set of resources necessary to
|
5
|
+
# process one or more queues with a given concurrency.
|
6
|
+
# One "default" Capsule is started but the user may declare additional
|
7
|
+
# Capsules in their initializer.
|
8
|
+
#
|
9
|
+
# This capsule will pull jobs from the "single" queue and process
|
10
|
+
# the jobs with one thread, meaning the jobs will be processed serially.
|
11
|
+
#
|
12
|
+
# Sidekiq.configure_server do |config|
|
13
|
+
# config.capsule("single-threaded") do |cap|
|
14
|
+
# cap.concurrency = 1
|
15
|
+
# cap.queues = %w(single)
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
class Capsule
|
19
|
+
include Sidekiq::Component
|
20
|
+
|
21
|
+
attr_reader :name
|
22
|
+
attr_reader :queues
|
23
|
+
attr_accessor :concurrency
|
24
|
+
attr_reader :mode
|
25
|
+
attr_reader :weights
|
26
|
+
|
27
|
+
def initialize(name, config)
|
28
|
+
@name = name
|
29
|
+
@config = config
|
30
|
+
@queues = ["default"]
|
31
|
+
@weights = {"default" => 0}
|
32
|
+
@concurrency = config[:concurrency]
|
33
|
+
@mode = :strict
|
34
|
+
end
|
35
|
+
|
36
|
+
def fetcher
|
37
|
+
@fetcher ||= begin
|
38
|
+
inst = (config[:fetch_class] || Sidekiq::BasicFetch).new(self)
|
39
|
+
inst.setup(config[:fetch_setup]) if inst.respond_to?(:setup)
|
40
|
+
inst
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def stop
|
45
|
+
fetcher&.bulk_requeue([])
|
46
|
+
end
|
47
|
+
|
48
|
+
# Sidekiq checks queues in three modes:
|
49
|
+
# - :strict - all queues have 0 weight and are checked strictly in order
|
50
|
+
# - :weighted - queues have arbitrary weight between 1 and N
|
51
|
+
# - :random - all queues have weight of 1
|
52
|
+
def queues=(val)
|
53
|
+
@weights = {}
|
54
|
+
@queues = Array(val).each_with_object([]) do |qstr, memo|
|
55
|
+
arr = qstr
|
56
|
+
arr = qstr.split(",") if qstr.is_a?(String)
|
57
|
+
name, weight = arr
|
58
|
+
@weights[name] = weight.to_i
|
59
|
+
[weight.to_i, 1].max.times do
|
60
|
+
memo << name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@mode = if @weights.values.all?(&:zero?)
|
64
|
+
:strict
|
65
|
+
elsif @weights.values.all? { |x| x == 1 }
|
66
|
+
:random
|
67
|
+
else
|
68
|
+
:weighted
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Allow the middleware to be different per-capsule.
|
73
|
+
# Avoid if possible and add middleware globally so all
|
74
|
+
# capsules share the same chains. Easier to debug that way.
|
75
|
+
def client_middleware
|
76
|
+
@client_chain ||= config.client_middleware.copy_for(self)
|
77
|
+
yield @client_chain if block_given?
|
78
|
+
@client_chain
|
79
|
+
end
|
80
|
+
|
81
|
+
def server_middleware
|
82
|
+
@server_chain ||= config.server_middleware.copy_for(self)
|
83
|
+
yield @server_chain if block_given?
|
84
|
+
@server_chain
|
85
|
+
end
|
86
|
+
|
87
|
+
def redis_pool
|
88
|
+
Thread.current[:sidekiq_redis_pool] || local_redis_pool
|
89
|
+
end
|
90
|
+
|
91
|
+
def local_redis_pool
|
92
|
+
# connection pool is lazy, it will not create connections unless you actually need them
|
93
|
+
# so don't be skimpy!
|
94
|
+
@redis ||= config.new_redis_pool(@concurrency, name)
|
95
|
+
end
|
96
|
+
|
97
|
+
def redis
|
98
|
+
raise ArgumentError, "requires a block" unless block_given?
|
99
|
+
redis_pool.with do |conn|
|
100
|
+
retryable = true
|
101
|
+
begin
|
102
|
+
yield conn
|
103
|
+
rescue RedisClientAdapter::BaseError => ex
|
104
|
+
# 2550 Failover can cause the server to become a replica, need
|
105
|
+
# to disconnect and reopen the socket to get back to the primary.
|
106
|
+
# 4495 Use the same logic if we have a "Not enough replicas" error from the primary
|
107
|
+
# 4985 Use the same logic when a blocking command is force-unblocked
|
108
|
+
# The same retry logic is also used in client.rb
|
109
|
+
if retryable && ex.message =~ /READONLY|NOREPLICAS|UNBLOCKED/
|
110
|
+
conn.close
|
111
|
+
retryable = false
|
112
|
+
retry
|
113
|
+
end
|
114
|
+
raise
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def lookup(name)
|
120
|
+
config.lookup(name)
|
121
|
+
end
|
122
|
+
|
123
|
+
def logger
|
124
|
+
config.logger
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -9,18 +9,23 @@ require "erb"
|
|
9
9
|
require "fileutils"
|
10
10
|
|
11
11
|
require "sidekiq"
|
12
|
+
require "sidekiq/config"
|
13
|
+
require "sidekiq/component"
|
14
|
+
require "sidekiq/capsule"
|
12
15
|
require "sidekiq/launcher"
|
13
|
-
require "sidekiq/util"
|
14
16
|
|
15
|
-
module Sidekiq
|
17
|
+
module Sidekiq # :nodoc:
|
16
18
|
class CLI
|
17
|
-
include
|
19
|
+
include Sidekiq::Component
|
18
20
|
include Singleton unless $TESTING
|
19
21
|
|
20
22
|
attr_accessor :launcher
|
21
23
|
attr_accessor :environment
|
24
|
+
attr_accessor :config
|
25
|
+
|
26
|
+
def parse(args = ARGV.dup)
|
27
|
+
@config ||= Sidekiq.default_configuration
|
22
28
|
|
23
|
-
def parse(args = ARGV)
|
24
29
|
setup_options(args)
|
25
30
|
initialize_logger
|
26
31
|
validate!
|
@@ -33,9 +38,10 @@ module Sidekiq
|
|
33
38
|
# Code within this method is not tested because it alters
|
34
39
|
# global process state irreversibly. PRs which improve the
|
35
40
|
# test coverage of Sidekiq::CLI are welcomed.
|
36
|
-
def run
|
37
|
-
|
38
|
-
|
41
|
+
def run(boot_app: true)
|
42
|
+
boot_application if boot_app
|
43
|
+
|
44
|
+
if environment == "development" && $stdout.tty? && @config.logger.formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
|
39
45
|
print_banner
|
40
46
|
end
|
41
47
|
logger.info "Booted Rails #{::Rails.version} application in #{environment} environment" if rails_app?
|
@@ -43,9 +49,17 @@ module Sidekiq
|
|
43
49
|
self_read, self_write = IO.pipe
|
44
50
|
sigs = %w[INT TERM TTIN TSTP]
|
45
51
|
# USR1 and USR2 don't work on the JVM
|
46
|
-
sigs << "USR2"
|
52
|
+
sigs << "USR2" if Sidekiq.pro? && !jruby?
|
47
53
|
sigs.each do |sig|
|
48
|
-
trap
|
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
|
62
|
+
end
|
49
63
|
self_write.puts(sig)
|
50
64
|
end
|
51
65
|
rescue ArgumentError
|
@@ -54,31 +68,45 @@ module Sidekiq
|
|
54
68
|
|
55
69
|
logger.info "Running in #{RUBY_DESCRIPTION}"
|
56
70
|
logger.info Sidekiq::LICENSE
|
57
|
-
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)
|
58
72
|
|
59
73
|
# touch the connection pool so it is created before we
|
60
74
|
# fire startup and start multithreading.
|
61
|
-
|
62
|
-
|
75
|
+
info = @config.redis_info
|
76
|
+
ver = Gem::Version.new(info["redis_version"])
|
77
|
+
raise "You are connecting to Redis #{ver}, Sidekiq requires Redis 6.2.0 or greater" if ver < Gem::Version.new("6.2.0")
|
78
|
+
|
79
|
+
maxmemory_policy = info["maxmemory_policy"]
|
80
|
+
if maxmemory_policy != "noeviction" && maxmemory_policy != ""
|
81
|
+
# Redis Enterprise Cloud returns "" for their policy 😳
|
82
|
+
logger.warn <<~EOM
|
83
|
+
|
84
|
+
|
85
|
+
WARNING: Your Redis instance will evict Sidekiq data under heavy load.
|
86
|
+
The 'noeviction' maxmemory policy is recommended (current policy: '#{maxmemory_policy}').
|
87
|
+
See: https://github.com/sidekiq/sidekiq/wiki/Using-Redis#memory
|
88
|
+
|
89
|
+
EOM
|
90
|
+
end
|
63
91
|
|
64
92
|
# Since the user can pass us a connection pool explicitly in the initializer, we
|
65
93
|
# need to verify the size is large enough or else Sidekiq's performance is dramatically slowed.
|
66
|
-
|
67
|
-
|
68
|
-
|
94
|
+
@config.capsules.each_pair do |name, cap|
|
95
|
+
raise ArgumentError, "Pool size too small for #{name}" if cap.redis_pool.size < cap.concurrency
|
96
|
+
end
|
69
97
|
|
70
98
|
# cache process identity
|
71
|
-
|
99
|
+
@config[:identity] = identity
|
72
100
|
|
73
101
|
# Touch middleware so it isn't lazy loaded by multiple threads, #3043
|
74
|
-
|
102
|
+
@config.server_middleware
|
75
103
|
|
76
104
|
# Before this point, the process is initializing with just the main thread.
|
77
105
|
# Starting here the process will now have multiple threads running.
|
78
106
|
fire_event(:startup, reverse: false, reraise: true)
|
79
107
|
|
80
|
-
logger.debug { "Client Middleware: #{
|
81
|
-
logger.debug { "Server Middleware: #{
|
108
|
+
logger.debug { "Client Middleware: #{@config.default_capsule.client_middleware.map(&:klass).join(", ")}" }
|
109
|
+
logger.debug { "Server Middleware: #{@config.default_capsule.server_middleware.map(&:klass).join(", ")}" }
|
82
110
|
|
83
111
|
launch(self_read)
|
84
112
|
end
|
@@ -88,13 +116,13 @@ module Sidekiq
|
|
88
116
|
logger.info "Starting processing, hit Ctrl-C to stop"
|
89
117
|
end
|
90
118
|
|
91
|
-
@launcher = Sidekiq::Launcher.new(
|
119
|
+
@launcher = Sidekiq::Launcher.new(@config)
|
92
120
|
|
93
121
|
begin
|
94
122
|
launcher.run
|
95
123
|
|
96
|
-
while
|
97
|
-
signal =
|
124
|
+
while self_read.wait_readable
|
125
|
+
signal = self_read.gets.strip
|
98
126
|
handle_signal(signal)
|
99
127
|
end
|
100
128
|
rescue Interrupt
|
@@ -111,19 +139,34 @@ module Sidekiq
|
|
111
139
|
end
|
112
140
|
end
|
113
141
|
|
114
|
-
|
115
|
-
|
142
|
+
HOLIDAY_COLORS = {
|
143
|
+
# got other color-specific holidays from around the world?
|
144
|
+
# https://developer-book.com/post/definitive-guide-for-colored-text-in-terminal/#256-color-escape-codes
|
145
|
+
"3-17" => "\e[1;32m", # St. Patrick's Day green
|
146
|
+
"10-31" => "\e[38;5;208m" # Halloween orange
|
147
|
+
}
|
148
|
+
|
149
|
+
def self.day
|
150
|
+
@@day ||= begin
|
151
|
+
t = Date.today
|
152
|
+
"#{t.month}-#{t.day}"
|
153
|
+
end
|
116
154
|
end
|
117
155
|
|
118
156
|
def self.r
|
119
|
-
"\e[31m"
|
157
|
+
@@r ||= HOLIDAY_COLORS[day] || "\e[1;31m"
|
120
158
|
end
|
121
159
|
|
122
160
|
def self.b
|
123
|
-
"\e[30m"
|
161
|
+
@@b ||= HOLIDAY_COLORS[day] || "\e[30m"
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.w
|
165
|
+
"\e[1;37m"
|
124
166
|
end
|
125
167
|
|
126
168
|
def self.reset
|
169
|
+
@@b = @@r = @@day = nil
|
127
170
|
"\e[0m"
|
128
171
|
end
|
129
172
|
|
@@ -136,7 +179,7 @@ module Sidekiq
|
|
136
179
|
#{w} ,$$$$$b#{b}/#{w}md$$$P^'
|
137
180
|
#{w} .d$$$$$$#{b}/#{w}$$$P'
|
138
181
|
#{w} $$^' `"#{b}/#{w}$$$' #{r}____ _ _ _ _
|
139
|
-
#{w} $:
|
182
|
+
#{w} $: #{b}'#{w},$$: #{r} / ___|(_) __| | ___| | _(_) __ _
|
140
183
|
#{w} `b :$$ #{r} \\___ \\| |/ _` |/ _ \\ |/ / |/ _` |
|
141
184
|
#{w} $$: #{r} ___) | | (_| | __/ <| | (_| |
|
142
185
|
#{w} $$ #{r}|____/|_|\\__,_|\\___|_|\\_\\_|\\__, |
|
@@ -151,25 +194,25 @@ module Sidekiq
|
|
151
194
|
# Heroku sends TERM and then waits 30 seconds for process to exit.
|
152
195
|
"TERM" => ->(cli) { raise Interrupt },
|
153
196
|
"TSTP" => ->(cli) {
|
154
|
-
|
197
|
+
cli.logger.info "Received TSTP, no longer accepting new work"
|
155
198
|
cli.launcher.quiet
|
156
199
|
},
|
157
200
|
"TTIN" => ->(cli) {
|
158
201
|
Thread.list.each do |thread|
|
159
|
-
|
202
|
+
cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
|
160
203
|
if thread.backtrace
|
161
|
-
|
204
|
+
cli.logger.warn thread.backtrace.join("\n")
|
162
205
|
else
|
163
|
-
|
206
|
+
cli.logger.warn "<no backtrace available>"
|
164
207
|
end
|
165
208
|
end
|
166
|
-
}
|
209
|
+
}
|
167
210
|
}
|
168
|
-
UNHANDLED_SIGNAL_HANDLER = ->(cli) {
|
211
|
+
UNHANDLED_SIGNAL_HANDLER = ->(cli) { cli.logger.info "No signal handler registered, ignoring" }
|
169
212
|
SIGNAL_HANDLERS.default = UNHANDLED_SIGNAL_HANDLER
|
170
213
|
|
171
214
|
def handle_signal(sig)
|
172
|
-
|
215
|
+
logger.debug "Got #{sig} signal"
|
173
216
|
SIGNAL_HANDLERS[sig].call(self)
|
174
217
|
end
|
175
218
|
|
@@ -182,7 +225,12 @@ module Sidekiq
|
|
182
225
|
end
|
183
226
|
|
184
227
|
def set_environment(cli_env)
|
185
|
-
|
228
|
+
# See #984 for discussion.
|
229
|
+
# APP_ENV is now the preferred ENV term since it is not tech-specific.
|
230
|
+
# Both Sinatra 2.0+ and Sidekiq support this term.
|
231
|
+
# RAILS_ENV and RACK_ENV are there for legacy support.
|
232
|
+
@environment = cli_env || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
233
|
+
config[:environment] = @environment
|
186
234
|
end
|
187
235
|
|
188
236
|
def symbolize_keys_deep!(hash)
|
@@ -211,7 +259,7 @@ module Sidekiq
|
|
211
259
|
config_dir = if File.directory?(opts[:require].to_s)
|
212
260
|
File.join(opts[:require], "config")
|
213
261
|
else
|
214
|
-
File.join(
|
262
|
+
File.join(@config[:require], "config")
|
215
263
|
end
|
216
264
|
|
217
265
|
%w[sidekiq.yml sidekiq.yml.erb].each do |config_file|
|
@@ -224,32 +272,38 @@ module Sidekiq
|
|
224
272
|
opts = parse_config(opts[:config_file]).merge(opts) if opts[:config_file]
|
225
273
|
|
226
274
|
# set defaults
|
227
|
-
opts[:queues] = ["default"] if opts[:queues].nil?
|
228
|
-
opts[:strict] = true if opts[:strict].nil?
|
275
|
+
opts[:queues] = ["default"] if opts[:queues].nil?
|
229
276
|
opts[:concurrency] = Integer(ENV["RAILS_MAX_THREADS"]) if opts[:concurrency].nil? && ENV["RAILS_MAX_THREADS"]
|
230
277
|
|
231
278
|
# merge with defaults
|
232
|
-
|
233
|
-
|
279
|
+
@config.merge!(opts)
|
280
|
+
|
281
|
+
@config.default_capsule.tap do |cap|
|
282
|
+
cap.queues = opts[:queues]
|
283
|
+
cap.concurrency = opts[:concurrency] || @config[:concurrency]
|
284
|
+
end
|
234
285
|
|
235
|
-
|
236
|
-
|
286
|
+
opts[:capsules]&.each do |name, cap_config|
|
287
|
+
@config.capsule(name.to_s) do |cap|
|
288
|
+
cap.queues = cap_config[:queues]
|
289
|
+
cap.concurrency = cap_config[:concurrency]
|
290
|
+
end
|
291
|
+
end
|
237
292
|
end
|
238
293
|
|
239
|
-
def
|
294
|
+
def boot_application
|
240
295
|
ENV["RACK_ENV"] = ENV["RAILS_ENV"] = environment
|
241
296
|
|
242
|
-
if File.directory?(
|
297
|
+
if File.directory?(@config[:require])
|
243
298
|
require "rails"
|
244
|
-
if ::Rails::VERSION::MAJOR <
|
245
|
-
|
246
|
-
else
|
247
|
-
require "sidekiq/rails"
|
248
|
-
require File.expand_path("#{options[:require]}/config/environment.rb")
|
299
|
+
if ::Rails::VERSION::MAJOR < 6
|
300
|
+
warn "Sidekiq #{Sidekiq::VERSION} only supports Rails 6+"
|
249
301
|
end
|
250
|
-
|
302
|
+
require "sidekiq/rails"
|
303
|
+
require File.expand_path("#{@config[:require]}/config/environment.rb")
|
304
|
+
@config[:tag] ||= default_tag
|
251
305
|
else
|
252
|
-
require
|
306
|
+
require @config[:require]
|
253
307
|
end
|
254
308
|
end
|
255
309
|
|
@@ -266,18 +320,18 @@ module Sidekiq
|
|
266
320
|
end
|
267
321
|
|
268
322
|
def validate!
|
269
|
-
if !File.exist?(
|
270
|
-
(File.directory?(
|
323
|
+
if !File.exist?(@config[:require]) ||
|
324
|
+
(File.directory?(@config[:require]) && !File.exist?("#{@config[:require]}/config/application.rb"))
|
271
325
|
logger.info "=================================================================="
|
272
326
|
logger.info " Please point Sidekiq to a Rails application or a Ruby file "
|
273
|
-
logger.info " to load your
|
327
|
+
logger.info " to load your job classes with -r [DIR|FILE]."
|
274
328
|
logger.info "=================================================================="
|
275
329
|
logger.info @parser
|
276
330
|
die(1)
|
277
331
|
end
|
278
332
|
|
279
333
|
[:concurrency, :timeout].each do |opt|
|
280
|
-
raise ArgumentError, "#{opt}: #{
|
334
|
+
raise ArgumentError, "#{opt}: #{@config[opt]} is not a valid value" if @config[opt].to_i <= 0
|
281
335
|
end
|
282
336
|
end
|
283
337
|
|
@@ -294,10 +348,6 @@ module Sidekiq
|
|
294
348
|
opts[:concurrency] = Integer(arg)
|
295
349
|
end
|
296
350
|
|
297
|
-
o.on "-d", "--daemon", "Daemonize process" do |arg|
|
298
|
-
puts "ERROR: Daemonization mode was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
|
299
|
-
end
|
300
|
-
|
301
351
|
o.on "-e", "--environment ENV", "Application environment" do |arg|
|
302
352
|
opts[:environment] = arg
|
303
353
|
end
|
@@ -307,11 +357,11 @@ module Sidekiq
|
|
307
357
|
end
|
308
358
|
|
309
359
|
o.on "-q", "--queue QUEUE[,WEIGHT]", "Queues to process with optional weights" do |arg|
|
310
|
-
|
311
|
-
|
360
|
+
opts[:queues] ||= []
|
361
|
+
opts[:queues] << arg
|
312
362
|
end
|
313
363
|
|
314
|
-
o.on "-r", "--require [PATH|DIR]", "Location of Rails application with
|
364
|
+
o.on "-r", "--require [PATH|DIR]", "Location of Rails application with jobs or file to require" do |arg|
|
315
365
|
opts[:require] = arg
|
316
366
|
end
|
317
367
|
|
@@ -327,15 +377,7 @@ module Sidekiq
|
|
327
377
|
opts[:config_file] = arg
|
328
378
|
end
|
329
379
|
|
330
|
-
o.on "-
|
331
|
-
puts "ERROR: Logfile redirection was removed in Sidekiq 6.0, Sidekiq will only log to STDOUT"
|
332
|
-
end
|
333
|
-
|
334
|
-
o.on "-P", "--pidfile PATH", "path to pidfile" do |arg|
|
335
|
-
puts "ERROR: PID file creation was removed in Sidekiq 6.0, please use a proper process supervisor to start and manage your services"
|
336
|
-
end
|
337
|
-
|
338
|
-
o.on "-V", "--version", "Print version and exit" do |arg|
|
380
|
+
o.on "-V", "--version", "Print version and exit" do
|
339
381
|
puts "Sidekiq #{Sidekiq::VERSION}"
|
340
382
|
die(0)
|
341
383
|
end
|
@@ -351,11 +393,13 @@ module Sidekiq
|
|
351
393
|
end
|
352
394
|
|
353
395
|
def initialize_logger
|
354
|
-
|
396
|
+
@config.logger.level = ::Logger::DEBUG if @config[:verbose]
|
355
397
|
end
|
356
398
|
|
357
399
|
def parse_config(path)
|
358
|
-
|
400
|
+
erb = ERB.new(File.read(path), trim_mode: "-")
|
401
|
+
erb.filename = File.expand_path(path)
|
402
|
+
opts = YAML.safe_load(erb.result, permitted_classes: [Symbol], aliases: true) || {}
|
359
403
|
|
360
404
|
if opts.respond_to? :deep_symbolize_keys!
|
361
405
|
opts.deep_symbolize_keys!
|
@@ -364,24 +408,16 @@ module Sidekiq
|
|
364
408
|
end
|
365
409
|
|
366
410
|
opts = opts.merge(opts.delete(environment.to_sym) || {})
|
367
|
-
|
411
|
+
opts.delete(:strict)
|
368
412
|
|
369
413
|
opts
|
370
414
|
end
|
371
415
|
|
372
|
-
def parse_queues(opts, queues_and_weights)
|
373
|
-
queues_and_weights.each { |queue_and_weight| parse_queue(opts, *queue_and_weight) }
|
374
|
-
end
|
375
|
-
|
376
|
-
def parse_queue(opts, queue, weight = nil)
|
377
|
-
opts[:queues] ||= []
|
378
|
-
raise ArgumentError, "queues: #{queue} cannot be defined twice" if opts[:queues].include?(queue)
|
379
|
-
[weight.to_i, 1].max.times { opts[:queues] << queue }
|
380
|
-
opts[:strict] = false if weight.to_i > 0
|
381
|
-
end
|
382
|
-
|
383
416
|
def rails_app?
|
384
|
-
defined?(::Rails)
|
417
|
+
defined?(::Rails) && ::Rails.respond_to?(:application)
|
385
418
|
end
|
386
419
|
end
|
387
420
|
end
|
421
|
+
|
422
|
+
require "sidekiq/systemd"
|
423
|
+
require "sidekiq/metrics/tracking"
|