Skip to content

Commit

Permalink
workers watch master and graceful shutdown if it dies
Browse files Browse the repository at this point in the history
  • Loading branch information
nevans committed Jul 28, 2010
1 parent 7263f5c commit a244669
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 6 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,18 @@ The pool master responds to the following signals:
So you should probably use a config file. After a `HUP`, workers that are no
longer needed will be gracefully shutdown via `QUIT`.

Other Features
--------------

Workers will watch the pool master, and gracefully shutdown if the master
process dies (for whatever reason) before them.

TODO
-----

* figure out a good way to test this (preferably via cucumber or rspec)
* clean up the code (I stole most of it from unicorn, and it's still a bit
bastardized)
* workers should watch for the pool master, and gracefully die if pool master
disapears (normally parent will send QUIT on exit)
* do appropriate logging (e.g. all to one logfile, each queue to its own
logfile, or each worker to its own logfile). Logfile location must be
configurable.
Expand Down
5 changes: 2 additions & 3 deletions lib/resque/pool.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- encoding: utf-8 -*-
require 'resque'
require 'resque/pool/logging'
require 'resque/pool/pooled_worker'
require 'fcntl'
require 'yaml'

Expand Down Expand Up @@ -288,12 +289,10 @@ def spawn_worker!(queues)

def create_worker(queues)
queues = queues.to_s.split(',')
worker = Resque::Worker.new(*queues)
worker = PooledWorker.new(*queues)
worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
worker.very_verbose = ENV['VVERBOSE']
worker
rescue Resque::NoQueueError
abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
end

# }}}
Expand Down
65 changes: 65 additions & 0 deletions lib/resque/pool/pooled_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
class Resque::Pool

class PooledWorker < ::Resque::Worker

def initialize(*args)
@pool_master_pid = Process.pid
super
end

def pool_master_has_gone_away?
@pool_master_pid && @pool_master_pid != Process.ppid
end

# this allows us to shutdown
def shutdown
@shutdown || pool_master_has_gone_away?
end

# this entire method (except for one line) is copied and pasted from
# resque-1.9.9. If shutdown were used as a method (attr_reader) rather
# than an instance variable, I wouldn't need to reduplicate this. :-(
#
# hopefully I can get defunkt to accept my patch for this.
# Until it is, the resque-pool gem will depend on an exact version of
# resque.
def work(interval = 5, &block)
$0 = "resque: Starting"
startup

loop do
#### THIS IS THE ONLY LINE THAT IS CHANGED
break if shutdown
#### THAT WAS THE ONLY LINE THAT WAS CHANGED

if not @paused and job = reserve
log "got: #{job.inspect}"
run_hook :before_fork
working_on job

if @child = fork
rand # Reseeding
procline "Forked #{@child} at #{Time.now.to_i}"
Process.wait
else
procline "Processing #{job.queue} since #{Time.now.to_i}"
perform(job, &block)
exit! unless @cant_fork
end

done_working
@child = nil
else
break if interval.to_i == 0
log! "Sleeping for #{interval.to_i}"
procline @paused ? "Paused" : "Waiting for #{@queues.join(',')}"
sleep interval.to_i
end
end

ensure
unregister_worker
end
end

end
2 changes: 1 addition & 1 deletion resque-pool.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.required_rubygems_version = ">= 1.3.6"

s.add_development_dependency "rspec"
s.add_dependency "resque", "~> 1.9.1"
s.add_dependency "resque", "=1.9.9"

s.files = Dir.glob("lib/**/*")
s.require_path = 'lib'
Expand Down

0 comments on commit a244669

Please sign in to comment.