sidekiq 6.4.0 → 6.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9622b2851203b0c5a80695ab7801ca77e15dc63a641ae79132cda9a2fcbe0cc6
4
- data.tar.gz: dd943a02d2cf910f51866d02254f3a7845cb159735bd54d223dd7127a1fbd2fa
3
+ metadata.gz: 70d899b76bdd764a2ec7e5f23b6d056494b58897daaf49db672daad3e0f60237
4
+ data.tar.gz: daae0430ecaf8eb7f172c70e628581c20a17e1a7cb1a58170b9082fc3dde1ea2
5
5
  SHA512:
6
- metadata.gz: 65bcd542866d8699ecf5958d81a15fd322cd1c51dfc1dbc6a8b15402b70862510c134e2b0ed9f9dbcdbb4dea3a59c1d12878ff926145e503079a59896f279ff3
7
- data.tar.gz: 36143e85dc7fd4611f8a43fe39788dc590725ac63a827fbc174916da2d59fdadb3fb64fa0d819c4ef90694f6f292ea15f7fb58fb29f368c0a06c5b90f1b4bca7
6
+ metadata.gz: 930a0feb7ff47473eb995f8ba695468498afecb311c25296c93042ecfa00cd2bf48e19efd5ba775b4895c065705a344043e0c0e5d7b4115c2dceb1ec7cf341f9
7
+ data.tar.gz: 14ab645609e7c9f3fa954432097cd46d6e9e74e5bddc9ed1541697d13f3399add407ffb5af23c89c82651793c97e2c54b8fd4f845ca20287ce6bf033fd9caed2
data/Changes.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/mperham/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/main/Ent-Changes.md)
4
4
 
5
+ 6.4.2
6
+ ---------
7
+
8
+ - Strict argument checking now runs after client-side middleware [#5246]
9
+ - Fix page events with live polling [#5184]
10
+ - Many under-the-hood changes to remove all usage of the term "worker"
11
+ from the Sidekiq codebase and APIs. This mostly involved RDoc and local
12
+ variable names but a few constants and public APIs were changed. The old
13
+ APIs will be removed in Sidekiq 7.0.
14
+ ```
15
+ Sidekiq::DEFAULT_WORKER_OPTIONS -> Sidekiq.default_job_options
16
+ Sidekiq.default_worker_options -> Sidekiq.default_job_options
17
+ Sidekiq::Queues["default"].jobs_by_worker(HardJob) -> Sidekiq::Queues["default"].jobs_by_class(HardJob)
18
+ ```
19
+
20
+ 6.4.1
21
+ ---------
22
+
23
+ - Fix pipeline/multi deprecations in redis-rb 4.6
24
+ - Fix sidekiq.yml YAML load errors on Ruby 3.1 [#5141]
25
+ - Sharding support for `perform_bulk` [#5129]
26
+ - Refactor job logger for SPEEEEEEED
27
+
5
28
  6.4.0
6
29
  ---------
7
30
 
@@ -27,7 +50,6 @@ bin/rails generate sidekiq:job ProcessOrderJob
27
50
  ```
28
51
  - Fix job retries losing CurrentAttributes [#5090]
29
52
  - Tweak shutdown to give long-running threads time to cleanup [#5095]
30
- - Add keyword arguments support in extensions
31
53
 
32
54
  6.3.1
33
55
  ---------
@@ -312,6 +334,13 @@ See the [Logging wiki page](https://github.com/mperham/sidekiq/wiki/Logging) for
312
334
  - Integrate the StandardRB code formatter to ensure consistent code
313
335
  styling. [#4114, gearnode]
314
336
 
337
+ 5.2.10
338
+ ---------
339
+
340
+ - Backport fix for CVE-2022-23837.
341
+ - Migrate to `exists?` for redis-rb.
342
+ - Lock redis-rb to <4.6 to avoid deprecations.
343
+
315
344
  5.2.9
316
345
  ---------
317
346
 
data/README.md CHANGED
@@ -36,7 +36,7 @@ Sidekiq 6.0 supports Rails 5.0+ but does not require it.
36
36
  Installation
37
37
  -----------------
38
38
 
39
- gem install sidekiq
39
+ bundle add sidekiq
40
40
 
41
41
 
42
42
  Getting Started
@@ -80,6 +80,11 @@ Useful resources:
80
80
  Every Friday morning is Sidekiq happy hour: I video chat and answer questions.
81
81
  See the [Sidekiq support page](https://sidekiq.org/support.html) for details.
82
82
 
83
+ Contributing
84
+ -----------------
85
+
86
+ Please see [the contributing guidelines](https://github.com/mperham/sidekiq/blob/main/.github/contributing.md).
87
+
83
88
 
84
89
  License
85
90
  -----------------
data/bin/sidekiq CHANGED
@@ -4,7 +4,7 @@
4
4
  # RUBYOPT=-w bundle exec sidekiq
5
5
  $TESTING = false
6
6
 
7
- require_relative '../lib/sidekiq/cli'
7
+ require_relative "../lib/sidekiq/cli"
8
8
 
9
9
  def integrate_with_systemd
10
10
  return unless ENV["NOTIFY_SOCKET"]
@@ -32,8 +32,8 @@ begin
32
32
  rescue => e
33
33
  raise e if $DEBUG
34
34
  if Sidekiq.error_handlers.length == 0
35
- STDERR.puts e.message
36
- STDERR.puts e.backtrace.join("\n")
35
+ warn e.message
36
+ warn e.backtrace.join("\n")
37
37
  else
38
38
  cli.handle_exception e
39
39
  end
data/bin/sidekiqload CHANGED
@@ -4,19 +4,18 @@
4
4
  # RUBYOPT=-w bundle exec sidekiq
5
5
  $TESTING = false
6
6
 
7
- #require 'ruby-prof'
8
- require 'bundler/setup'
7
+ # require "ruby-prof"
8
+ require "bundler/setup"
9
9
  Bundler.require(:default, :load_test)
10
10
 
11
- require_relative '../lib/sidekiq/cli'
12
- require_relative '../lib/sidekiq/launcher'
13
-
14
- include Sidekiq::Util
11
+ require_relative "../lib/sidekiq/cli"
12
+ require_relative "../lib/sidekiq/launcher"
15
13
 
16
14
  Sidekiq.configure_server do |config|
17
15
  config.options[:concurrency] = 10
18
- config.redis = { db: 13, port: 6380, driver: :hiredis }
19
- config.options[:queues] << 'default'
16
+ config.redis = {db: 13, port: 6380}
17
+ # config.redis = { db: 13, port: 6380, driver: :hiredis}
18
+ config.options[:queues] << "default"
20
19
  config.logger.level = Logger::ERROR
21
20
  config.average_scheduled_poll_interval = 2
22
21
  config.reliable! if defined?(Sidekiq::Pro)
@@ -29,53 +28,50 @@ class LoadWorker
29
28
  1
30
29
  end
31
30
 
32
- def perform(idx, ts=nil)
33
- puts(Time.now.to_f - ts) if ts != nil
34
- #raise idx.to_s if idx % 100 == 1
31
+ def perform(idx, ts = nil)
32
+ puts(Time.now.to_f - ts) if !ts.nil?
33
+ # raise idx.to_s if idx % 100 == 1
35
34
  end
36
35
  end
37
36
 
38
37
  # brew tap shopify/shopify
39
38
  # brew install toxiproxy
40
- # gem install toxiproxy
41
39
  # run `toxiproxy-server` in a separate terminal window.
42
- require 'toxiproxy'
40
+ require "toxiproxy"
43
41
  # simulate a non-localhost network for realer-world conditions.
44
42
  # adding 1ms of network latency has an ENORMOUS impact on benchmarks
45
43
  Toxiproxy.populate([{
46
- "name": "redis",
47
- "listen": "127.0.0.1:6380",
48
- "upstream": "127.0.0.1:6379"
44
+ name: "redis",
45
+ listen: "127.0.0.1:6380",
46
+ upstream: "127.0.0.1:6379"
49
47
  }])
50
48
 
51
49
  self_read, self_write = IO.pipe
52
- %w(INT TERM TSTP TTIN).each do |sig|
53
- begin
54
- trap sig do
55
- self_write.puts(sig)
56
- end
57
- rescue ArgumentError
58
- puts "Signal #{sig} not supported"
50
+ %w[INT TERM TSTP TTIN].each do |sig|
51
+ trap sig do
52
+ self_write.puts(sig)
59
53
  end
54
+ rescue ArgumentError
55
+ puts "Signal #{sig} not supported"
60
56
  end
61
57
 
62
- Sidekiq.redis {|c| c.flushdb}
58
+ Sidekiq.redis { |c| c.flushdb }
63
59
  def handle_signal(launcher, sig)
64
60
  Sidekiq.logger.debug "Got #{sig} signal"
65
61
  case sig
66
- when 'INT'
62
+ when "INT"
67
63
  # Handle Ctrl-C in JRuby like MRI
68
64
  # http://jira.codehaus.org/browse/JRUBY-4637
69
65
  raise Interrupt
70
- when 'TERM'
66
+ when "TERM"
71
67
  # Heroku sends TERM and then waits 30 seconds for process to exit.
72
68
  raise Interrupt
73
- when 'TSTP'
69
+ when "TSTP"
74
70
  Sidekiq.logger.info "Received TSTP, no longer accepting new work"
75
71
  launcher.quiet
76
- when 'TTIN'
72
+ when "TTIN"
77
73
  Thread.list.each do |thread|
78
- Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread['label']}"
74
+ Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
79
75
  if thread.backtrace
80
76
  Sidekiq.logger.warn thread.backtrace.join("\n")
81
77
  else
@@ -89,50 +85,46 @@ def Process.rss
89
85
  `ps -o rss= -p #{Process.pid}`.chomp.to_i
90
86
  end
91
87
 
92
- iter = 10
88
+ iter = 50
93
89
  count = 10_000
94
90
 
95
91
  iter.times do
96
- arr = Array.new(count) do
97
- []
98
- end
99
- count.times do |idx|
100
- arr[idx][0] = idx
101
- end
102
- Sidekiq::Client.push_bulk('class' => LoadWorker, 'args' => arr)
92
+ arr = Array.new(count) { |idx| [idx] }
93
+ Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr)
103
94
  end
104
- Sidekiq.logger.error "Created #{count*iter} jobs"
95
+ Sidekiq.logger.error "Created #{count * iter} jobs"
105
96
 
106
97
  start = Time.now
107
98
 
108
99
  Monitoring = Thread.new do
109
- watchdog("monitor thread") do
110
- while true
100
+ while true
101
+ sleep 0.2
102
+ qsize = Sidekiq.redis do |conn|
103
+ conn.llen "queue:default"
104
+ end
105
+ total = qsize
106
+ # Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
107
+ if total == 0
108
+ Sidekiq.logger.error("Done, #{iter * count} jobs in #{Time.now - start} sec")
109
+ Sidekiq.logger.error("Now here's the latency for three jobs")
110
+
111
+ LoadWorker.perform_async(1, Time.now.to_f)
112
+ LoadWorker.perform_async(2, Time.now.to_f)
113
+ LoadWorker.perform_async(3, Time.now.to_f)
114
+
111
115
  sleep 0.2
112
- qsize = Sidekiq.redis do |conn|
113
- conn.llen "queue:default"
114
- end
115
- total = qsize
116
- #Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
117
- if total == 0
118
- Sidekiq.logger.error("Done, #{iter * count} jobs in #{Time.now - start} sec")
119
- Sidekiq.logger.error("Now here's the latency for three jobs")
120
-
121
- LoadWorker.perform_async(1, Time.now.to_f)
122
- LoadWorker.perform_async(2, Time.now.to_f)
123
- LoadWorker.perform_async(3, Time.now.to_f)
124
-
125
- sleep 0.2
126
- exit(0)
127
- end
116
+ exit(0)
128
117
  end
129
118
  end
130
119
  end
131
120
 
132
121
  begin
133
- #RubyProf::exclude_threads = [ Monitoring ]
134
- #RubyProf.start
135
- fire_event(:startup)
122
+ # RubyProf::exclude_threads = [ Monitoring ]
123
+ # RubyProf.start
124
+ events = Sidekiq.options[:lifecycle_events][:startup]
125
+ events.each(&:call)
126
+ events.clear
127
+
136
128
  Sidekiq.logger.error "Simulating 1ms of latency between Sidekiq and redis"
137
129
  Toxiproxy[:redis].downstream(:latency, latency: 1).apply do
138
130
  launcher = Sidekiq::Launcher.new(Sidekiq.options)
@@ -144,14 +136,14 @@ begin
144
136
  end
145
137
  end
146
138
  rescue SystemExit => e
147
- #Sidekiq.logger.error("Profiling...")
148
- #result = RubyProf.stop
149
- #printer = RubyProf::GraphHtmlPrinter.new(result)
150
- #printer.print(File.new("output.html", "w"), :min_percent => 1)
139
+ # Sidekiq.logger.error("Profiling...")
140
+ # result = RubyProf.stop
141
+ # printer = RubyProf::GraphHtmlPrinter.new(result)
142
+ # printer.print(File.new("output.html", "w"), :min_percent => 1)
151
143
  # normal
152
144
  rescue => e
153
145
  raise e if $DEBUG
154
- STDERR.puts e.message
155
- STDERR.puts e.backtrace.join("\n")
146
+ warn e.message
147
+ warn e.backtrace.join("\n")
156
148
  exit 1
157
149
  end
data/bin/sidekiqmon CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'sidekiq/monitor'
3
+ require "sidekiq/monitor"
4
4
 
5
5
  section = "all"
6
6
  section = ARGV[0] if ARGV.size == 1
data/lib/sidekiq/api.rb CHANGED
@@ -54,14 +54,14 @@ module Sidekiq
54
54
  # O(1) redis calls
55
55
  def fetch_stats_fast!
56
56
  pipe1_res = Sidekiq.redis { |conn|
57
- conn.pipelined do
58
- conn.get("stat:processed")
59
- conn.get("stat:failed")
60
- conn.zcard("schedule")
61
- conn.zcard("retry")
62
- conn.zcard("dead")
63
- conn.scard("processes")
64
- conn.lrange("queue:default", -1, -1)
57
+ conn.pipelined do |pipeline|
58
+ pipeline.get("stat:processed")
59
+ pipeline.get("stat:failed")
60
+ pipeline.zcard("schedule")
61
+ pipeline.zcard("retry")
62
+ pipeline.zcard("dead")
63
+ pipeline.scard("processes")
64
+ pipeline.lrange("queue:default", -1, -1)
65
65
  end
66
66
  }
67
67
 
@@ -101,9 +101,9 @@ module Sidekiq
101
101
  }
102
102
 
103
103
  pipe2_res = Sidekiq.redis { |conn|
104
- conn.pipelined do
105
- processes.each { |key| conn.hget(key, "busy") }
106
- queues.each { |queue| conn.llen("queue:#{queue}") }
104
+ conn.pipelined do |pipeline|
105
+ processes.each { |key| pipeline.hget(key, "busy") }
106
+ queues.each { |queue| pipeline.llen("queue:#{queue}") }
107
107
  end
108
108
  }
109
109
 
@@ -147,9 +147,9 @@ module Sidekiq
147
147
  Sidekiq.redis do |conn|
148
148
  queues = conn.sscan_each("queues").to_a
149
149
 
150
- lengths = conn.pipelined {
150
+ lengths = conn.pipelined { |pipeline|
151
151
  queues.each do |queue|
152
- conn.llen("queue:#{queue}")
152
+ pipeline.llen("queue:#{queue}")
153
153
  end
154
154
  }
155
155
 
@@ -287,9 +287,9 @@ module Sidekiq
287
287
 
288
288
  def clear
289
289
  Sidekiq.redis do |conn|
290
- conn.multi do
291
- conn.unlink(@rname)
292
- conn.srem("queues", name)
290
+ conn.multi do |transaction|
291
+ transaction.unlink(@rname)
292
+ transaction.srem("queues", name)
293
293
  end
294
294
  end
295
295
  end
@@ -354,27 +354,31 @@ module Sidekiq
354
354
  def display_args
355
355
  # Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
356
356
  @display_args ||= case klass
357
- when /\ASidekiq::Extensions::Delayed/
358
- safe_load(args[0], args) do |_, _, arg|
359
- arg
360
- end
361
- when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
362
- job_args = self["wrapped"] ? args[0]["arguments"] : []
363
- if (self["wrapped"] || args[0]) == "ActionMailer::DeliveryJob"
364
- # remove MailerClass, mailer_method and 'deliver_now'
365
- job_args.drop(3)
366
- elsif (self["wrapped"] || args[0]) == "ActionMailer::MailDeliveryJob"
367
- # remove MailerClass, mailer_method and 'deliver_now'
368
- job_args.drop(3).first["args"]
369
- else
370
- job_args
371
- end
372
- else
373
- if self["encrypt"]
374
- # no point in showing 150+ bytes of random garbage
375
- args[-1] = "[encrypted data]"
376
- end
377
- args
357
+ when /\ASidekiq::Extensions::Delayed/
358
+ safe_load(args[0], args) do |_, _, arg, kwarg|
359
+ if !kwarg || kwarg.empty?
360
+ arg
361
+ else
362
+ [arg, kwarg]
363
+ end
364
+ end
365
+ when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
366
+ job_args = self["wrapped"] ? args[0]["arguments"] : []
367
+ if (self["wrapped"] || args[0]) == "ActionMailer::DeliveryJob"
368
+ # remove MailerClass, mailer_method and 'deliver_now'
369
+ job_args.drop(3)
370
+ elsif (self["wrapped"] || args[0]) == "ActionMailer::MailDeliveryJob"
371
+ # remove MailerClass, mailer_method and 'deliver_now'
372
+ job_args.drop(3).first["args"]
373
+ else
374
+ job_args
375
+ end
376
+ else
377
+ if self["encrypt"]
378
+ # no point in showing 150+ bytes of random garbage
379
+ args[-1] = "[encrypted data]"
380
+ end
381
+ args
378
382
  end
379
383
  end
380
384
 
@@ -519,9 +523,9 @@ module Sidekiq
519
523
 
520
524
  def remove_job
521
525
  Sidekiq.redis do |conn|
522
- results = conn.multi {
523
- conn.zrangebyscore(parent.name, score, score)
524
- conn.zremrangebyscore(parent.name, score, score)
526
+ results = conn.multi { |transaction|
527
+ transaction.zrangebyscore(parent.name, score, score)
528
+ transaction.zremrangebyscore(parent.name, score, score)
525
529
  }.first
526
530
 
527
531
  if results.size == 1
@@ -542,9 +546,9 @@ module Sidekiq
542
546
  yield msg if msg
543
547
 
544
548
  # push the rest back onto the sorted set
545
- conn.multi do
549
+ conn.multi do |transaction|
546
550
  nonmatched.each do |message|
547
- conn.zadd(parent.name, score.to_f.to_s, message)
551
+ transaction.zadd(parent.name, score.to_f.to_s, message)
548
552
  end
549
553
  end
550
554
  end
@@ -731,10 +735,10 @@ module Sidekiq
731
735
  def kill(message, opts = {})
732
736
  now = Time.now.to_f
733
737
  Sidekiq.redis do |conn|
734
- conn.multi do
735
- conn.zadd(name, now.to_s, message)
736
- conn.zremrangebyscore(name, "-inf", now - self.class.timeout)
737
- conn.zremrangebyrank(name, 0, - self.class.max_jobs)
738
+ conn.multi do |transaction|
739
+ transaction.zadd(name, now.to_s, message)
740
+ transaction.zremrangebyscore(name, "-inf", now - self.class.timeout)
741
+ transaction.zremrangebyrank(name, 0, - self.class.max_jobs)
738
742
  end
739
743
  end
740
744
 
@@ -782,9 +786,9 @@ module Sidekiq
782
786
  count = 0
783
787
  Sidekiq.redis do |conn|
784
788
  procs = conn.sscan_each("processes").to_a.sort
785
- heartbeats = conn.pipelined {
789
+ heartbeats = conn.pipelined { |pipeline|
786
790
  procs.each do |key|
787
- conn.hget(key, "info")
791
+ pipeline.hget(key, "info")
788
792
  end
789
793
  }
790
794
 
@@ -806,9 +810,9 @@ module Sidekiq
806
810
  # We're making a tradeoff here between consuming more memory instead of
807
811
  # making more roundtrips to Redis, but if you have hundreds or thousands of workers,
808
812
  # you'll be happier this way
809
- conn.pipelined do
813
+ conn.pipelined do |pipeline|
810
814
  procs.each do |key|
811
- conn.hmget(key, "info", "busy", "beat", "quiet", "rss", "rtt_us")
815
+ pipeline.hmget(key, "info", "busy", "beat", "quiet", "rss", "rtt_us")
812
816
  end
813
817
  end
814
818
  }
@@ -922,9 +926,9 @@ module Sidekiq
922
926
  def signal(sig)
923
927
  key = "#{identity}-signals"
924
928
  Sidekiq.redis do |c|
925
- c.multi do
926
- c.lpush(key, sig)
927
- c.expire(key, 60)
929
+ c.multi do |transaction|
930
+ transaction.lpush(key, sig)
931
+ transaction.expire(key, 60)
928
932
  end
929
933
  end
930
934
  end
@@ -958,9 +962,9 @@ module Sidekiq
958
962
  Sidekiq.redis do |conn|
959
963
  procs = conn.sscan_each("processes").to_a
960
964
  procs.sort.each do |key|
961
- valid, workers = conn.pipelined {
962
- conn.exists?(key)
963
- conn.hgetall("#{key}:workers")
965
+ valid, workers = conn.pipelined { |pipeline|
966
+ pipeline.exists?(key)
967
+ pipeline.hgetall("#{key}:work")
964
968
  }
965
969
  next unless valid
966
970
  workers.each_pair do |tid, json|
@@ -988,9 +992,9 @@ module Sidekiq
988
992
  if procs.empty?
989
993
  0
990
994
  else
991
- conn.pipelined {
995
+ conn.pipelined { |pipeline|
992
996
  procs.each do |key|
993
- conn.hget(key, "busy")
997
+ pipeline.hget(key, "busy")
994
998
  end
995
999
  }.sum(&:to_i)
996
1000
  end
data/lib/sidekiq/cli.rb CHANGED
@@ -20,7 +20,7 @@ module Sidekiq
20
20
  attr_accessor :launcher
21
21
  attr_accessor :environment
22
22
 
23
- def parse(args = ARGV)
23
+ def parse(args = ARGV.dup)
24
24
  setup_options(args)
25
25
  initialize_logger
26
26
  validate!
@@ -115,8 +115,8 @@ module Sidekiq
115
115
  begin
116
116
  launcher.run
117
117
 
118
- while (readable_io = IO.select([self_read]))
119
- signal = readable_io.first[0].gets.strip
118
+ while self_read.wait_readable
119
+ signal = self_read.gets.strip
120
120
  handle_signal(signal)
121
121
  end
122
122
  rescue Interrupt
@@ -295,7 +295,7 @@ module Sidekiq
295
295
  (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
296
296
  logger.info "=================================================================="
297
297
  logger.info " Please point Sidekiq to a Rails application or a Ruby file "
298
- logger.info " to load your worker classes with -r [DIR|FILE]."
298
+ logger.info " to load your job classes with -r [DIR|FILE]."
299
299
  logger.info "=================================================================="
300
300
  logger.info @parser
301
301
  die(1)
@@ -336,7 +336,7 @@ module Sidekiq
336
336
  parse_queue opts, queue, weight
337
337
  end
338
338
 
339
- o.on "-r", "--require [PATH|DIR]", "Location of Rails application with workers or file to require" do |arg|
339
+ o.on "-r", "--require [PATH|DIR]", "Location of Rails application with jobs or file to require" do |arg|
340
340
  opts[:require] = arg
341
341
  end
342
342
 
@@ -382,7 +382,7 @@ module Sidekiq
382
382
  def parse_config(path)
383
383
  erb = ERB.new(File.read(path))
384
384
  erb.filename = File.expand_path(path)
385
- opts = YAML.load(erb.result) || {}
385
+ opts = load_yaml(erb.result) || {}
386
386
 
387
387
  if opts.respond_to? :deep_symbolize_keys!
388
388
  opts.deep_symbolize_keys!
@@ -398,6 +398,14 @@ module Sidekiq
398
398
  opts
399
399
  end
400
400
 
401
+ def load_yaml(src)
402
+ if Psych::VERSION > "4.0"
403
+ YAML.safe_load(src, permitted_classes: [Symbol], aliases: true)
404
+ else
405
+ YAML.load(src)
406
+ end
407
+ end
408
+
401
409
  def parse_queues(opts, queues_and_weights)
402
410
  queues_and_weights.each { |queue_and_weight| parse_queue(opts, *queue_and_weight) }
403
411
  end