Skip to content

Instantly share code, notes, and snippets.

@jsierles
Created January 28, 2010 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsierles/288852 to your computer and use it in GitHub Desktop.
Save jsierles/288852 to your computer and use it in GitHub Desktop.
A passenger-like proxy for development environments with unicorn
# gem install em-proxy
require 'rubygems'
require 'em-proxy'
APP_ROOT = File.expand_path(ARGV[0])
module Unicorn
module RestartHandler
def file_modified
puts "#{path} modified"
Manager.restart(File.dirname(path) + "/..")
end
end
class Manager
def self.start(dir, port)
if !File.exists?("#{dir}/tmp/pids/unicorn.pid")
puts "Start unicorn for #{dir} on #{port}"
Dir.chdir(dir)
cmd = File.exists?("#{dir}/config.ru") ? "unicorn -D -p #{port} config.ru" : "unicorn_rails -D -p #{port}"
system cmd
end
end
def self.monitor_for_restart(dir)
puts "Start monitoring app at #{dir}"
EM.watch_file("#{dir}/tmp/restart.txt", RestartHandler)
end
def self.stop(dir)
if File.exists?("#{dir}/tmp/pids/unicorn.pid")
Process.kill('TERM', File.read("#{dir}/tmp/pids/unicorn.pid"))
end
end
def self.restart(dir)
if File.exists?("#{dir}/tmp/pids/unicorn.pid")
Process.kill('HUP', File.read("#{dir}/tmp/pids/unicorn.pid"))
end
end
end
end
EM.kqueue = true if EM.kqueue? # file watching requires kqueue on OSX
Proxy.start(:host => "0.0.0.0", :port => ARGV[1].to_i) do |conn|
conn.on_data do |data|
server = data.scan(/\r\nHost: (.+)\r\n/).flatten.to_s.sub(/:\d+$/, '').split('.').last(2).first
dir = "#{APP_ROOT}/#{server}"
if !conn.instance_variable_get("@servers")[server]
if File.directory?(dir)
port = "37#{server.sum.to_s[0,3]}"
conn.server server, :host => "127.0.0.1", :port => port
Unicorn::Manager.start(dir, port)
Unicorn::Manager.monitor_for_restart(dir)
puts "sending request to #{server} on port #{port}"
[data, [server]]
else
puts "no app directory found for #{server}"
conn.send_data "HTTP/1.1 404 Not Found\r\nConnection: close\r\n<html>No app directory found for #{server}</html>"
end
end
end
conn.on_response do |backend, resp|
resp
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment