sidekiq 0.8.0 → 0.9.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.
- data/Changes.md +11 -0
- data/Gemfile +7 -1
- data/LICENSE +7 -1
- data/README.md +2 -0
- data/TODO.md +1 -2
- data/bin/sidekiq +1 -1
- data/config.ru +8 -0
- data/examples/config.yml +0 -2
- data/examples/scheduling.rb +37 -0
- data/lib/sidekiq.rb +25 -11
- data/lib/sidekiq/capistrano.rb +8 -5
- data/lib/sidekiq/cli.rb +20 -21
- data/lib/sidekiq/client.rb +9 -6
- data/lib/sidekiq/extensions/action_mailer.rb +1 -2
- data/lib/sidekiq/extensions/active_record.rb +1 -3
- data/lib/sidekiq/extensions/generic_proxy.rb +1 -1
- data/lib/sidekiq/manager.rb +28 -22
- data/lib/sidekiq/middleware/client/unique_jobs.rb +3 -3
- data/lib/sidekiq/middleware/server/failure_jobs.rb +1 -1
- data/lib/sidekiq/middleware/server/unique_jobs.rb +1 -1
- data/lib/sidekiq/processor.rb +4 -6
- data/lib/sidekiq/rails.rb +16 -1
- data/lib/sidekiq/redis_connection.rb +3 -3
- data/lib/sidekiq/util.rb +3 -15
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +93 -0
- data/lib/sidekiq/worker.rb +0 -4
- data/myapp/Gemfile +15 -3
- data/myapp/app/controllers/work_controller.rb +1 -1
- data/myapp/config/initializers/sidekiq.rb +2 -2
- data/myapp/config/routes.rb +2 -2
- data/sidekiq.gemspec +3 -1
- data/test/helper.rb +4 -0
- data/test/test_cli.rb +26 -14
- data/test/test_client.rb +2 -2
- data/test/test_extensions.rb +11 -7
- data/test/test_manager.rb +2 -3
- data/test/test_middleware.rb +1 -1
- data/test/test_stats.rb +28 -29
- data/test/test_testing.rb +47 -14
- data/test/test_web.rb +51 -0
- data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
- data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
- data/web/assets/javascripts/application.js +3 -0
- data/web/assets/javascripts/vendor/bootstrap.js +12 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-alert.js +91 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-button.js +98 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-carousel.js +154 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-collapse.js +136 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-dropdown.js +92 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-modal.js +210 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-popover.js +95 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-scrollspy.js +125 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tab.js +130 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-tooltip.js +270 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-transition.js +51 -0
- data/web/assets/javascripts/vendor/bootstrap/bootstrap-typeahead.js +271 -0
- data/web/assets/javascripts/vendor/jquery.js +9266 -0
- data/web/assets/stylesheets/application.css +11 -0
- data/web/assets/stylesheets/vendor/bootstrap-responsive.css +567 -0
- data/web/assets/stylesheets/vendor/bootstrap.css +3365 -0
- data/web/views/index.slim +42 -0
- data/web/views/layout.slim +24 -0
- data/web/views/queue.slim +11 -0
- metadata +71 -22
- data/lib/sidekiq/middleware/client/resque_web_compatibility.rb +0 -14
data/Changes.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.9.0
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- Add -t option to configure the TERM shutdown timeout
|
5
|
+
- TERM shutdown timeout is now configurable, defaults to 5 seconds.
|
6
|
+
- USR1 signal now stops Sidekiq from accepting new work,
|
7
|
+
capistrano sends USR1 at start of deploy and TERM at end of deploy
|
8
|
+
giving workers the maximum amount of time to finish.
|
9
|
+
- New Sidekiq::Web rack application available
|
10
|
+
- Updated Sidekiq.redis API
|
11
|
+
|
1
12
|
0.8.0
|
2
13
|
-----------
|
3
14
|
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
@@ -12,5 +12,11 @@ You may choose to license Sidekiq in one of two ways:
|
|
12
12
|
$50 to my Pledgie fund at http://www.pledgie.com/campaigns/16623 to use
|
13
13
|
this license.
|
14
14
|
|
15
|
-
|
15
|
+
The commercial license is just meant to help support my OSS work. If
|
16
16
|
you do buy the commercial licensing option, thank you for your support!
|
17
|
+
|
18
|
+
The commercial license is meant to be per-site. Consulting shops must buy
|
19
|
+
one license per client engagement which uses Sidekiq. For instance,
|
20
|
+
GitHub could license Sidekiq for $50 for their own internal use but they
|
21
|
+
must pay $50 per GitHub::FI install because FI is a separate installation
|
22
|
+
from the GitHub website managed by the FI customer.
|
data/README.md
CHANGED
@@ -42,6 +42,8 @@ More Information
|
|
42
42
|
-----------------
|
43
43
|
|
44
44
|
Please see the [sidekiq wiki](https://github.com/mperham/sidekiq/wiki) for more information.
|
45
|
+
[#sidekiq on irc.freenode.net](irc://irc.freenode.net/#sidekiq) is dedicated to this project,
|
46
|
+
but bug reports or feature requests suggestions should still go through [issues on Github](https://github.com/mperham/sidekiq/issues).
|
45
47
|
|
46
48
|
|
47
49
|
License
|
data/TODO.md
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
-
|
2
|
-
- scheduled tasks [GH-66]
|
1
|
+
- reschedule failed tasks
|
data/bin/sidekiq
CHANGED
data/config.ru
ADDED
data/examples/config.yml
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Sidekiq defers scheduling to other, better suited gems.
|
2
|
+
# If you want to run a job regularly, here's an example
|
3
|
+
# of using the 'whenever' gem to push jobs to Sidekiq
|
4
|
+
# regularly.
|
5
|
+
|
6
|
+
class MyWorker
|
7
|
+
include Sidekiq::Worker
|
8
|
+
|
9
|
+
def perform(count)
|
10
|
+
puts "Job ##{count}: Late night, so tired..."
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.late_night_work
|
14
|
+
10.times do |x|
|
15
|
+
perform_async(x)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Kick off a bunch of jobs early in the morning
|
21
|
+
every 1.day, :at => '4:30 am' do
|
22
|
+
runner "MyWorker.late_night_work"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class HourlyWorker
|
27
|
+
include Sidekiq::Worker
|
28
|
+
|
29
|
+
def perform
|
30
|
+
cleanup_database
|
31
|
+
format_hard_drive
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
|
36
|
+
runner "HourlyWorker.perform_async"
|
37
|
+
end
|
data/lib/sidekiq.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'sidekiq/version'
|
2
2
|
require 'sidekiq/client'
|
3
3
|
require 'sidekiq/worker'
|
4
|
-
require 'sidekiq/rails'
|
4
|
+
require 'sidekiq/rails'
|
5
5
|
require 'sidekiq/redis_connection'
|
6
6
|
|
7
|
-
require 'sidekiq/extensions/action_mailer'
|
8
|
-
require 'sidekiq/extensions/active_record'
|
7
|
+
require 'sidekiq/extensions/action_mailer'
|
8
|
+
require 'sidekiq/extensions/active_record'
|
9
9
|
|
10
10
|
module Sidekiq
|
11
11
|
|
@@ -14,6 +14,7 @@ module Sidekiq
|
|
14
14
|
:concurrency => 25,
|
15
15
|
:require => '.',
|
16
16
|
:environment => nil,
|
17
|
+
:timeout => 5,
|
17
18
|
}
|
18
19
|
|
19
20
|
def self.options
|
@@ -28,7 +29,7 @@ module Sidekiq
|
|
28
29
|
# Configuration for Sidekiq server, use like:
|
29
30
|
#
|
30
31
|
# Sidekiq.configure_server do |config|
|
31
|
-
# config.redis =
|
32
|
+
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/mydb' }
|
32
33
|
# config.server_middleware do |chain|
|
33
34
|
# chain.add MyServerHook
|
34
35
|
# end
|
@@ -41,7 +42,7 @@ module Sidekiq
|
|
41
42
|
# Configuration for Sidekiq client, use like:
|
42
43
|
#
|
43
44
|
# Sidekiq.configure_client do |config|
|
44
|
-
# config.redis =
|
45
|
+
# config.redis = { :namespace => 'myapp', :size => 1, :url => 'redis://myhost:8877/mydb' }
|
45
46
|
# end
|
46
47
|
def self.configure_client
|
47
48
|
yield self unless server?
|
@@ -51,21 +52,34 @@ module Sidekiq
|
|
51
52
|
defined?(Sidekiq::CLI)
|
52
53
|
end
|
53
54
|
|
54
|
-
def self.redis
|
55
|
+
def self.redis(&block)
|
55
56
|
@redis ||= Sidekiq::RedisConnection.create
|
57
|
+
if block_given?
|
58
|
+
@redis.with(&block)
|
59
|
+
else
|
60
|
+
Sidekiq::Util.logger.info "*****************************************************
|
61
|
+
Sidekiq.redis now takes a block:
|
62
|
+
|
63
|
+
Sidekiq.redis { |connection| connection.smembers('myset') }
|
64
|
+
|
65
|
+
Please update your code accordingly.
|
66
|
+
Called from #{caller[0]}
|
67
|
+
*****************************************************"
|
68
|
+
@redis
|
69
|
+
end
|
56
70
|
end
|
57
71
|
|
58
72
|
def self.redis=(hash)
|
59
|
-
if
|
60
|
-
|
73
|
+
@redis = if hash.is_a?(Hash)
|
74
|
+
RedisConnection.create(hash)
|
75
|
+
else
|
76
|
+
Sidekiq::Util.logger.info "*****************************************************
|
61
77
|
Sidekiq.redis now takes a Hash:
|
62
78
|
old: Sidekiq.redis = Sidekiq::RedisConnection.create(:url => 'redis://foo.com', :namespace => 'abc', :size => 12)
|
63
79
|
new: Sidekiq.redis = { :url => 'redis://foo.com', :namespace => 'xyz', :size => 12 }
|
64
80
|
Called from #{caller[0]}
|
65
81
|
*****************************************************"
|
66
|
-
|
67
|
-
else
|
68
|
-
@redis = RedisConnection.create(hash)
|
82
|
+
hash
|
69
83
|
end
|
70
84
|
end
|
71
85
|
|
data/lib/sidekiq/capistrano.rb
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
Capistrano::Configuration.instance.load do
|
2
|
+
before "deploy", "sidekiq:quiet"
|
2
3
|
after "deploy", "sidekiq:restart"
|
3
4
|
|
5
|
+
_cset(:sidekiq_timeout) { 5 }
|
6
|
+
|
4
7
|
namespace :sidekiq do
|
5
8
|
|
6
|
-
desc "
|
7
|
-
task :
|
8
|
-
run "cd #{current_path} && kill
|
9
|
+
desc "Quiet sidekiq (stop accepting new work)"
|
10
|
+
task :quiet do
|
11
|
+
run "cd #{current_path} && kill -USR1 `cat #{current_path}/tmp/pids/sidekiq.pid`"
|
9
12
|
end
|
10
13
|
|
11
14
|
desc "Stop sidekiq"
|
12
15
|
task :stop do
|
13
|
-
run "cd #{current_path} && kill `cat tmp/pids/sidekiq.pid`"
|
16
|
+
run "cd #{current_path} && kill `cat #{current_path}/tmp/pids/sidekiq.pid` && sleep #{fetch :sidekiq_timeout} && kill -9 `cat #{current_path}/tmp/pids/sidekiq.pid` ; rm #{current_path}/tmp/pids/sidekiq.pid"
|
14
17
|
end
|
15
18
|
|
16
19
|
desc "Start sidekiq"
|
17
20
|
task :start do
|
18
21
|
rails_env = fetch(:rails_env, "production")
|
19
|
-
run "cd #{current_path} && nohup bundle exec sidekiq -e #{rails_env} -C config/sidekiq.yml -P tmp/pids/sidekiq.pid
|
22
|
+
run "cd #{current_path} && nohup bundle exec sidekiq -e #{rails_env} -C #{current_path}/config/sidekiq.yml -P #{current_path}/tmp/pids/sidekiq.pid >> #{current_path}/log/sidekiq.log 2>&1 &"
|
20
23
|
end
|
21
24
|
|
22
25
|
desc "Restart sidekiq"
|
data/lib/sidekiq/cli.rb
CHANGED
@@ -9,7 +9,14 @@ trap 'TERM' do
|
|
9
9
|
Thread.main.raise Interrupt
|
10
10
|
end
|
11
11
|
|
12
|
+
trap 'USR1' do
|
13
|
+
Sidekiq::Util.logger.info "Received USR1, no longer accepting new work"
|
14
|
+
mgr = Sidekiq::CLI.instance.manager
|
15
|
+
mgr.stop! if mgr
|
16
|
+
end
|
17
|
+
|
12
18
|
require 'yaml'
|
19
|
+
require 'singleton'
|
13
20
|
require 'optparse'
|
14
21
|
require 'sidekiq'
|
15
22
|
require 'sidekiq/util'
|
@@ -18,40 +25,40 @@ require 'sidekiq/manager'
|
|
18
25
|
module Sidekiq
|
19
26
|
class CLI
|
20
27
|
include Util
|
28
|
+
include Singleton
|
21
29
|
|
22
30
|
# Used for CLI testing
|
23
|
-
attr_accessor :code
|
31
|
+
attr_accessor :code, :manager
|
24
32
|
|
25
33
|
def initialize
|
26
34
|
@code = nil
|
35
|
+
@manager = nil
|
27
36
|
end
|
28
37
|
|
29
38
|
def parse(args=ARGV)
|
39
|
+
@code = nil
|
30
40
|
Sidekiq::Util.logger
|
31
41
|
|
32
42
|
cli = parse_options(args)
|
33
43
|
config = parse_config(cli)
|
34
44
|
options.merge!(config.merge(cli))
|
35
45
|
|
36
|
-
|
46
|
+
Sidekiq::Util.logger.level = Logger::DEBUG if options[:verbose]
|
37
47
|
|
38
|
-
write_pid
|
39
48
|
validate!
|
49
|
+
write_pid
|
40
50
|
boot_system
|
41
51
|
end
|
42
52
|
|
43
53
|
def run
|
44
|
-
manager = Sidekiq::Manager.new(options)
|
54
|
+
@manager = Sidekiq::Manager.new(options)
|
45
55
|
begin
|
46
56
|
logger.info 'Starting processing, hit Ctrl-C to stop'
|
47
57
|
manager.start!
|
48
|
-
# HACK need to determine how to pause main thread while
|
49
|
-
# waiting for signals.
|
50
58
|
sleep
|
51
59
|
rescue Interrupt
|
52
|
-
# TODO Need clean shutdown support from Celluloid
|
53
60
|
logger.info 'Shutting down'
|
54
|
-
manager.stop!
|
61
|
+
manager.stop!(:shutdown => true, :timeout => options[:timeout])
|
55
62
|
manager.wait(:shutdown)
|
56
63
|
end
|
57
64
|
end
|
@@ -108,21 +115,17 @@ module Sidekiq
|
|
108
115
|
end
|
109
116
|
|
110
117
|
o.on "-v", "--verbose", "Print more verbose output" do
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
o.on "-n", "--namespace NAMESPACE", "namespace worker queues are under (DEPRECATED)" do |arg|
|
115
|
-
puts "Namespace support has been removed, see https://github.com/mperham/sidekiq/issues/61"
|
116
|
-
end
|
117
|
-
|
118
|
-
o.on "-s", "--server LOCATION", "Where to find Redis (DEPRECATED)" do |arg|
|
119
|
-
puts "Server location support has been removed, see https://github.com/mperham/sidekiq/issues/61"
|
118
|
+
Sidekiq::Util.logger.level = Logger::DEBUG
|
120
119
|
end
|
121
120
|
|
122
121
|
o.on '-e', '--environment ENV', "Application environment" do |arg|
|
123
122
|
opts[:environment] = arg
|
124
123
|
end
|
125
124
|
|
125
|
+
o.on '-t', '--timeout NUM', "Shutdown timeout" do |arg|
|
126
|
+
opts[:timeout] = arg.to_i
|
127
|
+
end
|
128
|
+
|
126
129
|
o.on '-r', '--require [PATH|DIR]', "Location of Rails application with workers or file to require" do |arg|
|
127
130
|
opts[:require] = arg
|
128
131
|
end
|
@@ -173,9 +176,5 @@ module Sidekiq
|
|
173
176
|
end
|
174
177
|
end
|
175
178
|
|
176
|
-
def set_logger_level_to_debug
|
177
|
-
Sidekiq::Util.logger.level = Logger::DEBUG
|
178
|
-
end
|
179
|
-
|
180
179
|
end
|
181
180
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'multi_json'
|
2
2
|
require 'redis'
|
3
3
|
|
4
|
-
require 'sidekiq/redis_connection'
|
5
4
|
require 'sidekiq/middleware/chain'
|
6
|
-
require 'sidekiq/middleware/client/resque_web_compatibility'
|
7
5
|
require 'sidekiq/middleware/client/unique_jobs'
|
8
6
|
|
9
7
|
module Sidekiq
|
@@ -16,16 +14,15 @@ module Sidekiq
|
|
16
14
|
def self.default_middleware
|
17
15
|
Middleware::Chain.new do |m|
|
18
16
|
m.add Middleware::Client::UniqueJobs
|
19
|
-
m.add Middleware::Client::ResqueWebCompatibility
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
23
20
|
def self.registered_workers
|
24
|
-
Sidekiq.redis.smembers('workers')
|
21
|
+
Sidekiq.redis { |x| x.smembers('workers') }
|
25
22
|
end
|
26
23
|
|
27
24
|
def self.registered_queues
|
28
|
-
Sidekiq.redis.smembers('queues')
|
25
|
+
Sidekiq.redis { |x| x.smembers('queues') }
|
29
26
|
end
|
30
27
|
|
31
28
|
def self.queue_mappings
|
@@ -44,7 +41,13 @@ module Sidekiq
|
|
44
41
|
|
45
42
|
pushed = false
|
46
43
|
Sidekiq.client_middleware.invoke(item, queue) do
|
47
|
-
|
44
|
+
payload = MultiJson.encode(item)
|
45
|
+
Sidekiq.redis do |conn|
|
46
|
+
conn.multi do
|
47
|
+
conn.sadd('queues', queue)
|
48
|
+
conn.rpush("queue:#{queue}", payload)
|
49
|
+
end
|
50
|
+
end
|
48
51
|
pushed = true
|
49
52
|
end
|
50
53
|
pushed
|
@@ -13,7 +13,7 @@ module Sidekiq
|
|
13
13
|
# to JSON and then deserialized on the other side back into a
|
14
14
|
# Ruby object.
|
15
15
|
obj = [@target, name, args]
|
16
|
-
|
16
|
+
@performable.perform_async(::YAML.dump(obj))
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -4,6 +4,7 @@ require 'multi_json'
|
|
4
4
|
|
5
5
|
require 'sidekiq/util'
|
6
6
|
require 'sidekiq/processor'
|
7
|
+
require 'connection_pool/version'
|
7
8
|
|
8
9
|
module Sidekiq
|
9
10
|
|
@@ -19,7 +20,8 @@ module Sidekiq
|
|
19
20
|
trap_exit :processor_died
|
20
21
|
|
21
22
|
def initialize(options={})
|
22
|
-
logger.info "Booting sidekiq #{Sidekiq::VERSION} with Redis at #{redis.client.location}"
|
23
|
+
logger.info "Booting sidekiq #{Sidekiq::VERSION} with Redis at #{redis {|x| x.client.location}}"
|
24
|
+
logger.info "Running in #{RUBY_DESCRIPTION}"
|
23
25
|
logger.debug { options.inspect }
|
24
26
|
@count = options[:concurrency] || 25
|
25
27
|
@queues = options[:queues]
|
@@ -30,33 +32,33 @@ module Sidekiq
|
|
30
32
|
@ready = @count.times.map { Processor.new_link(current_actor) }
|
31
33
|
end
|
32
34
|
|
33
|
-
def stop
|
35
|
+
def stop(options={})
|
36
|
+
shutdown = options[:shutdown]
|
37
|
+
timeout = options[:timeout]
|
38
|
+
|
34
39
|
@done = true
|
35
|
-
@ready.each
|
40
|
+
@ready.each { |x| x.terminate if x.alive? }
|
36
41
|
@ready.clear
|
37
42
|
|
38
|
-
redis
|
43
|
+
redis do |conn|
|
39
44
|
workers = conn.smembers('workers')
|
40
45
|
workers.each do |name|
|
41
46
|
conn.srem('workers', name) if name =~ /:#{process_id}-/
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
|
-
if
|
46
|
-
|
47
|
-
|
50
|
+
if shutdown
|
51
|
+
if @busy.empty?
|
52
|
+
# after(0) needed to avoid deadlock in Celluoid after USR1 + TERM
|
53
|
+
return after(0) { signal(:shutdown) }
|
54
|
+
else
|
55
|
+
logger.info { "Pausing #{timeout} seconds to allow workers to finish..." }
|
56
|
+
end
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
redis.with_connection do |conn|
|
53
|
-
conn.multi do
|
54
|
-
@busy.each do |busy|
|
55
|
-
conn.lpush("queue:#{busy.queue}", busy.msg)
|
56
|
-
end
|
57
|
-
end
|
58
|
+
after(timeout) do
|
59
|
+
@busy.each { |x| x.terminate if x.alive? }
|
60
|
+
signal(:shutdown)
|
58
61
|
end
|
59
|
-
signal(:shutdown)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
@@ -72,11 +74,11 @@ module Sidekiq
|
|
72
74
|
watchdog('sidekiq processor_done crashed!') do
|
73
75
|
@done_callback.call(processor) if @done_callback
|
74
76
|
@busy.delete(processor)
|
75
|
-
processor.msg = processor.queue = nil
|
76
77
|
if stopped?
|
77
78
|
processor.terminate if processor.alive?
|
79
|
+
signal(:shutdown) if @busy.empty?
|
78
80
|
else
|
79
|
-
@ready << processor
|
81
|
+
@ready << processor if processor.alive?
|
80
82
|
end
|
81
83
|
dispatch
|
82
84
|
end
|
@@ -88,18 +90,18 @@ module Sidekiq
|
|
88
90
|
unless stopped?
|
89
91
|
@ready << Processor.new_link(current_actor)
|
90
92
|
dispatch
|
93
|
+
else
|
94
|
+
signal(:shutdown) if @busy.empty?
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
94
98
|
private
|
95
99
|
|
96
100
|
def find_work(queue)
|
97
|
-
msg = redis.lpop("queue:#{queue}")
|
101
|
+
msg = redis { |x| x.lpop("queue:#{queue}") }
|
98
102
|
if msg
|
99
103
|
processor = @ready.pop
|
100
104
|
@busy << processor
|
101
|
-
processor.msg = msg
|
102
|
-
processor.queue = queue
|
103
105
|
processor.process!(MultiJson.decode(msg), queue)
|
104
106
|
end
|
105
107
|
!!msg
|
@@ -109,6 +111,10 @@ module Sidekiq
|
|
109
111
|
watchdog("Fatal error in sidekiq, dispatch loop died") do
|
110
112
|
return if stopped?
|
111
113
|
|
114
|
+
# This is a safety check to ensure we haven't leaked
|
115
|
+
# processors somehow.
|
116
|
+
raise "BUG: No processors, cannot continue!" if @ready.empty? && @busy.empty?
|
117
|
+
|
112
118
|
# Dispatch loop
|
113
119
|
loop do
|
114
120
|
break logger.debug('no processors') if @ready.empty?
|