sidekiq 6.0.4 → 7.0.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.

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