Skip to content

Instantly share code, notes, and snippets.

@oogali
Created October 5, 2012 08:43
Show Gist options
  • Save oogali/3838796 to your computer and use it in GitHub Desktop.
Save oogali/3838796 to your computer and use it in GitHub Desktop.
unicorn + rake voltron
require 'net/http'
namespace :server do
ROOT = ENV['HOME'] || File.expand_path('../../../', __FILE__)
PIDFILE = File.join(ROOT, 'shared/pids/server.pid')
def get_pid
# XXX: this should be more intelligent, and check if,
# a) the pid is still alive,
# b) pid is actually unicorn
raise 'Server is not running' unless File.exists? PIDFILE
File.read(PIDFILE).to_i
end
def send_signal(pid, signal = :INT)
Process.kill signal, pid
end
def do_start
system "cd #{ROOT}/current >/dev/null 2>&1 ; bundle exec unicorn_rails -c #{ROOT}/current/config/unicorn.rb -D"
end
def do_restart
pid = {}
pid[:old] = get_pid rescue nil
if pid[:old]
# hey! i want a new process
send_signal pid[:old], :USR2
# wait for unicorn to spawn new process
sleep 5
# get new pid, and compare with old
pid[:new] = get_pid
raise "Could not start new Unicorn master process" if pid[:old] == pid[:new]
# tell old process to stop handling new requests
send_signal pid[:old], :WINCH
# hit a healthcheck url in app, to make sure we're functioning
# XXX: port should be configurable
# XXX: url should be configurable, and NOT static
uri = URI.parse 'http://localhost:18241/favicon.ico'
resp = Net::HTTP.get_response uri rescue nil
# if url fetch failed, then go back to old process
unless resp and resp.code == '200'
send_signal pid[:old], :HUP
send_signal pid[:new], :QUIT
raise 'Started new Unicorn process, but it is not serving requests as expected, reverting...'
end
# kill the old process, notify user
send_signal pid[:old], :QUIT
puts "replaced app, pid #{pid[:old]} with #{pid[:new]}"
else
do_start
end
end
task :start do
do_start
end
task :stop do
send_signal get_pid
end
task :restart do
do_restart
end
end
desc 'Start the web application'
task :start => [ 'server:start' ]
desc 'Stop the web application'
task :stop => [ 'server:stop' ]
desc 'Restart the web application'
task :restart => [ 'server:restart' ]
task :default do
puts
puts 'rake <action>'
puts '* valid actions: start, stop, restart'
puts
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment