sidekiq 6.3.1 → 6.4.1
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 +34 -0
- data/LICENSE +3 -3
- data/README.md +6 -1
- data/bin/sidekiq +3 -3
- data/bin/sidekiqload +56 -58
- data/bin/sidekiqmon +1 -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 +49 -43
- data/lib/sidekiq/cli.rb +13 -3
- data/lib/sidekiq/client.rb +21 -40
- data/lib/sidekiq/delay.rb +2 -0
- data/lib/sidekiq/fetch.rb +2 -2
- data/lib/sidekiq/job_logger.rb +15 -27
- data/lib/sidekiq/job_retry.rb +6 -4
- data/lib/sidekiq/job_util.rb +65 -0
- data/lib/sidekiq/launcher.rb +27 -27
- data/lib/sidekiq/logger.rb +4 -0
- data/lib/sidekiq/manager.rb +7 -9
- data/lib/sidekiq/middleware/current_attributes.rb +6 -1
- data/lib/sidekiq/paginator.rb +8 -8
- data/lib/sidekiq/rails.rb +1 -1
- data/lib/sidekiq/scheduled.rb +13 -3
- data/lib/sidekiq/util.rb +13 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +5 -2
- data/lib/sidekiq/web/helpers.rb +1 -1
- data/lib/sidekiq/web.rb +3 -3
- data/lib/sidekiq/worker.rb +59 -8
- data/lib/sidekiq.rb +6 -0
- data/web/assets/stylesheets/application-dark.css +13 -17
- data/web/assets/stylesheets/application.css +5 -5
- metadata +8 -7
- data/lib/generators/sidekiq/worker_generator.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99c9e264c092b88ea726be158fafe5bbab91f82f4b5864dee406280622e98e4b
|
4
|
+
data.tar.gz: acd72bd99929d7c9d129cb9662276cc5adb7214de07cd4fc8accf6b9d521994a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 622c25276c017302c1a9d144e9366043ba359b2c3b0c57d4e7baad8f9de2e9c9969a86c91acdbefcf736af92e297c4e1fbe2008aa41e0c1accadda77dd0724f5
|
7
|
+
data.tar.gz: 7e64012a5368cb0158ecaa50cdea6447709a64dd3a2816b36a31e7f17d70fffff81bd8d317c0cc1f9a6317adcffad9c200c48f9ca4bf208afba819ff7a07738e
|
data/Changes.md
CHANGED
@@ -2,6 +2,40 @@
|
|
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
|
+
HEAD
|
6
|
+
---------
|
7
|
+
|
8
|
+
- Fix pipeline/multi deprecations in redis-rb 4.6
|
9
|
+
- Fix sidekiq.yml YAML load errors on Ruby 3.1 [#5141]
|
10
|
+
- Sharding support for `perform_bulk` [#5129]
|
11
|
+
- Refactor job logger for SPEEEEEEED
|
12
|
+
|
13
|
+
6.4.0
|
14
|
+
---------
|
15
|
+
|
16
|
+
- **SECURITY**: Validate input to avoid possible DoS in Web UI.
|
17
|
+
- Add **strict argument checking** [#5071]
|
18
|
+
Sidekiq will now log a warning if JSON-unsafe arguments are passed to `perform_async`.
|
19
|
+
Add `Sidekiq.strict_args!(false)` to your initializer to disable this warning.
|
20
|
+
This warning will switch to an exception in Sidekiq 7.0.
|
21
|
+
- Note that Delayed Extensions will be removed in Sidekiq 7.0 [#5076]
|
22
|
+
- Add `perform_{inline,sync}` in Sidekiq::Job to run a job synchronously [#5061, hasan-ally]
|
23
|
+
```ruby
|
24
|
+
SomeJob.perform_async(args...)
|
25
|
+
SomeJob.perform_sync(args...)
|
26
|
+
SomeJob.perform_inline(args...)
|
27
|
+
```
|
28
|
+
You can also dynamically redirect a job to run synchronously:
|
29
|
+
```ruby
|
30
|
+
SomeJob.set("sync": true).perform_async(args...) # will run via perform_inline
|
31
|
+
```
|
32
|
+
- Replace Sidekiq::Worker `app/workers` generator with Sidekiq::Job `app/sidekiq` generator [#5055]
|
33
|
+
```
|
34
|
+
bin/rails generate sidekiq:job ProcessOrderJob
|
35
|
+
```
|
36
|
+
- Fix job retries losing CurrentAttributes [#5090]
|
37
|
+
- Tweak shutdown to give long-running threads time to cleanup [#5095]
|
38
|
+
|
5
39
|
6.3.1
|
6
40
|
---------
|
7
41
|
|
data/LICENSE
CHANGED
@@ -4,6 +4,6 @@ Sidekiq is an Open Source project licensed under the terms of
|
|
4
4
|
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
5
5
|
for license text.
|
6
6
|
|
7
|
-
Sidekiq Pro
|
8
|
-
|
9
|
-
|
7
|
+
Sidekiq Pro and Sidekiq Enterprise have a commercial-friendly license.
|
8
|
+
You can find the commercial license in COMM-LICENSE.txt.
|
9
|
+
Please see https://sidekiq.org for purchasing options.
|
data/README.md
CHANGED
@@ -43,7 +43,7 @@ Getting Started
|
|
43
43
|
-----------------
|
44
44
|
|
45
45
|
See the [Getting Started wiki page](https://github.com/mperham/sidekiq/wiki/Getting-Started) and follow the simple setup process.
|
46
|
-
You can watch [this
|
46
|
+
You can watch [this YouTube playlist](https://www.youtube.com/playlist?list=PLjeHh2LSCFrWGT5uVjUuFKAcrcj5kSai1) to learn all about
|
47
47
|
Sidekiq and see its features in action. Here's the Web UI:
|
48
48
|
|
49
49
|
![Web UI](https://github.com/mperham/sidekiq/raw/main/examples/web-ui.png)
|
@@ -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
|
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
|
-
|
36
|
-
|
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
|
8
|
-
require
|
7
|
+
# require "ruby-prof"
|
8
|
+
require "bundler/setup"
|
9
9
|
Bundler.require(:default, :load_test)
|
10
10
|
|
11
|
-
require_relative
|
12
|
-
require_relative
|
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 = {
|
19
|
-
config.
|
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,9 +28,9 @@ 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
|
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
|
|
@@ -39,43 +38,41 @@ end
|
|
39
38
|
# brew install toxiproxy
|
40
39
|
# gem install toxiproxy
|
41
40
|
# run `toxiproxy-server` in a separate terminal window.
|
42
|
-
require
|
41
|
+
require "toxiproxy"
|
43
42
|
# simulate a non-localhost network for realer-world conditions.
|
44
43
|
# adding 1ms of network latency has an ENORMOUS impact on benchmarks
|
45
44
|
Toxiproxy.populate([{
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
name: "redis",
|
46
|
+
listen: "127.0.0.1:6380",
|
47
|
+
upstream: "127.0.0.1:6379"
|
49
48
|
}])
|
50
49
|
|
51
50
|
self_read, self_write = IO.pipe
|
52
|
-
%w
|
53
|
-
|
54
|
-
|
55
|
-
self_write.puts(sig)
|
56
|
-
end
|
57
|
-
rescue ArgumentError
|
58
|
-
puts "Signal #{sig} not supported"
|
51
|
+
%w[INT TERM TSTP TTIN].each do |sig|
|
52
|
+
trap sig do
|
53
|
+
self_write.puts(sig)
|
59
54
|
end
|
55
|
+
rescue ArgumentError
|
56
|
+
puts "Signal #{sig} not supported"
|
60
57
|
end
|
61
58
|
|
62
|
-
Sidekiq.redis {|c| c.flushdb}
|
59
|
+
Sidekiq.redis { |c| c.flushdb }
|
63
60
|
def handle_signal(launcher, sig)
|
64
61
|
Sidekiq.logger.debug "Got #{sig} signal"
|
65
62
|
case sig
|
66
|
-
when
|
63
|
+
when "INT"
|
67
64
|
# Handle Ctrl-C in JRuby like MRI
|
68
65
|
# http://jira.codehaus.org/browse/JRUBY-4637
|
69
66
|
raise Interrupt
|
70
|
-
when
|
67
|
+
when "TERM"
|
71
68
|
# Heroku sends TERM and then waits 30 seconds for process to exit.
|
72
69
|
raise Interrupt
|
73
|
-
when
|
70
|
+
when "TSTP"
|
74
71
|
Sidekiq.logger.info "Received TSTP, no longer accepting new work"
|
75
72
|
launcher.quiet
|
76
|
-
when
|
73
|
+
when "TTIN"
|
77
74
|
Thread.list.each do |thread|
|
78
|
-
Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread[
|
75
|
+
Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
|
79
76
|
if thread.backtrace
|
80
77
|
Sidekiq.logger.warn thread.backtrace.join("\n")
|
81
78
|
else
|
@@ -89,7 +86,7 @@ def Process.rss
|
|
89
86
|
`ps -o rss= -p #{Process.pid}`.chomp.to_i
|
90
87
|
end
|
91
88
|
|
92
|
-
iter =
|
89
|
+
iter = 50
|
93
90
|
count = 10_000
|
94
91
|
|
95
92
|
iter.times do
|
@@ -99,40 +96,41 @@ iter.times do
|
|
99
96
|
count.times do |idx|
|
100
97
|
arr[idx][0] = idx
|
101
98
|
end
|
102
|
-
Sidekiq::Client.push_bulk(
|
99
|
+
Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr)
|
103
100
|
end
|
104
|
-
Sidekiq.logger.error "Created #{count*iter} jobs"
|
101
|
+
Sidekiq.logger.error "Created #{count * iter} jobs"
|
105
102
|
|
106
103
|
start = Time.now
|
107
104
|
|
108
105
|
Monitoring = Thread.new do
|
109
|
-
|
110
|
-
|
106
|
+
while true
|
107
|
+
sleep 0.2
|
108
|
+
qsize = Sidekiq.redis do |conn|
|
109
|
+
conn.llen "queue:default"
|
110
|
+
end
|
111
|
+
total = qsize
|
112
|
+
# Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
|
113
|
+
if total == 0
|
114
|
+
Sidekiq.logger.error("Done, #{iter * count} jobs in #{Time.now - start} sec")
|
115
|
+
Sidekiq.logger.error("Now here's the latency for three jobs")
|
116
|
+
|
117
|
+
LoadWorker.perform_async(1, Time.now.to_f)
|
118
|
+
LoadWorker.perform_async(2, Time.now.to_f)
|
119
|
+
LoadWorker.perform_async(3, Time.now.to_f)
|
120
|
+
|
111
121
|
sleep 0.2
|
112
|
-
|
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
|
122
|
+
exit(0)
|
128
123
|
end
|
129
124
|
end
|
130
125
|
end
|
131
126
|
|
132
127
|
begin
|
133
|
-
#RubyProf::exclude_threads = [ Monitoring ]
|
134
|
-
#RubyProf.start
|
135
|
-
|
128
|
+
# RubyProf::exclude_threads = [ Monitoring ]
|
129
|
+
# RubyProf.start
|
130
|
+
events = Sidekiq.options[:lifecycle_events][:startup]
|
131
|
+
events.each(&:call)
|
132
|
+
events.clear
|
133
|
+
|
136
134
|
Sidekiq.logger.error "Simulating 1ms of latency between Sidekiq and redis"
|
137
135
|
Toxiproxy[:redis].downstream(:latency, latency: 1).apply do
|
138
136
|
launcher = Sidekiq::Launcher.new(Sidekiq.options)
|
@@ -144,14 +142,14 @@ begin
|
|
144
142
|
end
|
145
143
|
end
|
146
144
|
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)
|
145
|
+
# Sidekiq.logger.error("Profiling...")
|
146
|
+
# result = RubyProf.stop
|
147
|
+
# printer = RubyProf::GraphHtmlPrinter.new(result)
|
148
|
+
# printer.print(File.new("output.html", "w"), :min_percent => 1)
|
151
149
|
# normal
|
152
150
|
rescue => e
|
153
151
|
raise e if $DEBUG
|
154
|
-
|
155
|
-
|
152
|
+
warn e.message
|
153
|
+
warn e.backtrace.join("\n")
|
156
154
|
exit 1
|
157
155
|
end
|
data/bin/sidekiqmon
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "rails/generators/named_base"
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
module Generators # :nodoc:
|
5
|
+
class JobGenerator < ::Rails::Generators::NamedBase # :nodoc:
|
6
|
+
desc "This generator creates a Sidekiq Job in app/sidekiq and a corresponding test"
|
7
|
+
|
8
|
+
check_class_collision suffix: "Job"
|
9
|
+
|
10
|
+
def self.default_generator_root
|
11
|
+
File.dirname(__FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_job_file
|
15
|
+
template "job.rb.erb", File.join("app/sidekiq", class_path, "#{file_name}_job.rb")
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_test_file
|
19
|
+
return unless test_framework
|
20
|
+
|
21
|
+
if test_framework == :rspec
|
22
|
+
create_job_spec
|
23
|
+
else
|
24
|
+
create_job_test
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def create_job_spec
|
31
|
+
template_file = File.join(
|
32
|
+
"spec/sidekiq",
|
33
|
+
class_path,
|
34
|
+
"#{file_name}_job_spec.rb"
|
35
|
+
)
|
36
|
+
template "job_spec.rb.erb", template_file
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_job_test
|
40
|
+
template_file = File.join(
|
41
|
+
"test/sidekiq",
|
42
|
+
class_path,
|
43
|
+
"#{file_name}_job_test.rb"
|
44
|
+
)
|
45
|
+
template "job_test.rb.erb", template_file
|
46
|
+
end
|
47
|
+
|
48
|
+
def file_name
|
49
|
+
@_file_name ||= super.sub(/_?job\z/i, "")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_framework
|
53
|
+
::Rails.application.config.generators.options[:rails][:test_framework]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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|
|
106
|
-
queues.each { |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
|
-
|
152
|
+
pipeline.llen("queue:#{queue}")
|
153
153
|
end
|
154
154
|
}
|
155
155
|
|
@@ -161,6 +161,8 @@ module Sidekiq
|
|
161
161
|
|
162
162
|
class History
|
163
163
|
def initialize(days_previous, start_date = nil)
|
164
|
+
# we only store five years of data in Redis
|
165
|
+
raise ArgumentError if days_previous < 1 || days_previous > (5 * 365)
|
164
166
|
@days_previous = days_previous
|
165
167
|
@start_date = start_date || Time.now.utc.to_date
|
166
168
|
end
|
@@ -285,9 +287,9 @@ module Sidekiq
|
|
285
287
|
|
286
288
|
def clear
|
287
289
|
Sidekiq.redis do |conn|
|
288
|
-
conn.multi do
|
289
|
-
|
290
|
-
|
290
|
+
conn.multi do |transaction|
|
291
|
+
transaction.unlink(@rname)
|
292
|
+
transaction.srem("queues", name)
|
291
293
|
end
|
292
294
|
end
|
293
295
|
end
|
@@ -353,8 +355,12 @@ module Sidekiq
|
|
353
355
|
# Unwrap known wrappers so they show up in a human-friendly manner in the Web UI
|
354
356
|
@display_args ||= case klass
|
355
357
|
when /\ASidekiq::Extensions::Delayed/
|
356
|
-
safe_load(args[0], args) do |_, _, arg|
|
357
|
-
|
358
|
+
safe_load(args[0], args) do |_, _, arg, kwarg|
|
359
|
+
if !kwarg || kwarg.empty?
|
360
|
+
arg
|
361
|
+
else
|
362
|
+
[arg, kwarg]
|
363
|
+
end
|
358
364
|
end
|
359
365
|
when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
360
366
|
job_args = self["wrapped"] ? args[0]["arguments"] : []
|
@@ -517,9 +523,9 @@ module Sidekiq
|
|
517
523
|
|
518
524
|
def remove_job
|
519
525
|
Sidekiq.redis do |conn|
|
520
|
-
results = conn.multi {
|
521
|
-
|
522
|
-
|
526
|
+
results = conn.multi { |transaction|
|
527
|
+
transaction.zrangebyscore(parent.name, score, score)
|
528
|
+
transaction.zremrangebyscore(parent.name, score, score)
|
523
529
|
}.first
|
524
530
|
|
525
531
|
if results.size == 1
|
@@ -540,9 +546,9 @@ module Sidekiq
|
|
540
546
|
yield msg if msg
|
541
547
|
|
542
548
|
# push the rest back onto the sorted set
|
543
|
-
conn.multi do
|
549
|
+
conn.multi do |transaction|
|
544
550
|
nonmatched.each do |message|
|
545
|
-
|
551
|
+
transaction.zadd(parent.name, score.to_f.to_s, message)
|
546
552
|
end
|
547
553
|
end
|
548
554
|
end
|
@@ -729,10 +735,10 @@ module Sidekiq
|
|
729
735
|
def kill(message, opts = {})
|
730
736
|
now = Time.now.to_f
|
731
737
|
Sidekiq.redis do |conn|
|
732
|
-
conn.multi do
|
733
|
-
|
734
|
-
|
735
|
-
|
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)
|
736
742
|
end
|
737
743
|
end
|
738
744
|
|
@@ -780,9 +786,9 @@ module Sidekiq
|
|
780
786
|
count = 0
|
781
787
|
Sidekiq.redis do |conn|
|
782
788
|
procs = conn.sscan_each("processes").to_a.sort
|
783
|
-
heartbeats = conn.pipelined {
|
789
|
+
heartbeats = conn.pipelined { |pipeline|
|
784
790
|
procs.each do |key|
|
785
|
-
|
791
|
+
pipeline.hget(key, "info")
|
786
792
|
end
|
787
793
|
}
|
788
794
|
|
@@ -804,9 +810,9 @@ module Sidekiq
|
|
804
810
|
# We're making a tradeoff here between consuming more memory instead of
|
805
811
|
# making more roundtrips to Redis, but if you have hundreds or thousands of workers,
|
806
812
|
# you'll be happier this way
|
807
|
-
conn.pipelined do
|
813
|
+
conn.pipelined do |pipeline|
|
808
814
|
procs.each do |key|
|
809
|
-
|
815
|
+
pipeline.hmget(key, "info", "busy", "beat", "quiet", "rss", "rtt_us")
|
810
816
|
end
|
811
817
|
end
|
812
818
|
}
|
@@ -819,10 +825,10 @@ module Sidekiq
|
|
819
825
|
|
820
826
|
hash = Sidekiq.load_json(info)
|
821
827
|
yield Process.new(hash.merge("busy" => busy.to_i,
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
828
|
+
"beat" => at_s.to_f,
|
829
|
+
"quiet" => quiet,
|
830
|
+
"rss" => rss.to_i,
|
831
|
+
"rtt_us" => rtt.to_i))
|
826
832
|
end
|
827
833
|
end
|
828
834
|
|
@@ -920,9 +926,9 @@ module Sidekiq
|
|
920
926
|
def signal(sig)
|
921
927
|
key = "#{identity}-signals"
|
922
928
|
Sidekiq.redis do |c|
|
923
|
-
c.multi do
|
924
|
-
|
925
|
-
|
929
|
+
c.multi do |transaction|
|
930
|
+
transaction.lpush(key, sig)
|
931
|
+
transaction.expire(key, 60)
|
926
932
|
end
|
927
933
|
end
|
928
934
|
end
|
@@ -956,9 +962,9 @@ module Sidekiq
|
|
956
962
|
Sidekiq.redis do |conn|
|
957
963
|
procs = conn.sscan_each("processes").to_a
|
958
964
|
procs.sort.each do |key|
|
959
|
-
valid, workers = conn.pipelined {
|
960
|
-
|
961
|
-
|
965
|
+
valid, workers = conn.pipelined { |pipeline|
|
966
|
+
pipeline.exists?(key)
|
967
|
+
pipeline.hgetall("#{key}:workers")
|
962
968
|
}
|
963
969
|
next unless valid
|
964
970
|
workers.each_pair do |tid, json|
|
@@ -986,9 +992,9 @@ module Sidekiq
|
|
986
992
|
if procs.empty?
|
987
993
|
0
|
988
994
|
else
|
989
|
-
conn.pipelined {
|
995
|
+
conn.pipelined { |pipeline|
|
990
996
|
procs.each do |key|
|
991
|
-
|
997
|
+
pipeline.hget(key, "busy")
|
992
998
|
end
|
993
999
|
}.sum(&:to_i)
|
994
1000
|
end
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -115,8 +115,8 @@ module Sidekiq
|
|
115
115
|
begin
|
116
116
|
launcher.run
|
117
117
|
|
118
|
-
while (readable_io =
|
119
|
-
signal = readable_io.
|
118
|
+
while (readable_io = self_read.wait_readable)
|
119
|
+
signal = readable_io.gets.strip
|
120
120
|
handle_signal(signal)
|
121
121
|
end
|
122
122
|
rescue Interrupt
|
@@ -380,7 +380,9 @@ module Sidekiq
|
|
380
380
|
end
|
381
381
|
|
382
382
|
def parse_config(path)
|
383
|
-
|
383
|
+
erb = ERB.new(File.read(path))
|
384
|
+
erb.filename = File.expand_path(path)
|
385
|
+
opts = load_yaml(erb.result) || {}
|
384
386
|
|
385
387
|
if opts.respond_to? :deep_symbolize_keys!
|
386
388
|
opts.deep_symbolize_keys!
|
@@ -396,6 +398,14 @@ module Sidekiq
|
|
396
398
|
opts
|
397
399
|
end
|
398
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
|
+
|
399
409
|
def parse_queues(opts, queues_and_weights)
|
400
410
|
queues_and_weights.each { |queue_and_weight| parse_queue(opts, *queue_and_weight) }
|
401
411
|
end
|