Skip to content

Commit

Permalink
Some renaming and minor refactors in rolling restart. Add some specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
macournoyer committed Nov 5, 2009
1 parent 327ef1e commit db14076
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 9 deletions.
27 changes: 19 additions & 8 deletions lib/thin/controllers/cluster.rb
@@ -1,6 +1,9 @@
require 'socket'

module Thin
# An exception class to handle the event that server didn't start on time
class RestartTimeout < RuntimeError; end

module Controllers
# Control a set of servers.
# * Generate start and stop commands and run them.
Expand All @@ -12,7 +15,7 @@ class Cluster < Controller
CLUSTER_OPTIONS = [:servers, :only, :onebyone, :wait]

# Maximum wait time for the server to be restarted
MAXIMUM_WAIT_TIME = 30 # seconds
DEFAULT_WAIT_TIME = 30 # seconds

# Create a new cluster of servers launched using +options+.
def initialize(options)
Expand All @@ -31,9 +34,6 @@ def only; @options[:only] end
def onebyone; @options[:onebyone] end
def wait; @options[:wait] end

# An exception class to handle the event that server didn't start on time
class ServerNotStartedInTimeError < RuntimeError; end

def swiftiply?
@options.has_key?(:swiftiply)
end
Expand Down Expand Up @@ -79,22 +79,33 @@ def restart
end
end

def test_socket(number)
if socket
UNIXSocket.new(socket_for(number))
else
TCPSocket.new(address, number)
end
rescue
nil
end

# Make sure the server is running before moving on to the next one.
def wait_until_server_started(number)
tries = 0
log "Waiting for server to start ..."
STDOUT.flush # Need this to make sure user got the message

tries = 0
loop do
test_socket = (socket ? UNIXSocket.new(socket_for(number)) : TCPSocket.new("127.0.0.1", number)) rescue nil
if test_socket
if test_socket = test_socket(number)
test_socket.close
break
elsif tries < wait
sleep 1
tries += 1
else
raise ServerNotStartedInTimeError, "The server didn't start in time. Please look at server's log file for more information, or set the value of 'wait' in your config file to be higher (defaults: 30)."
raise RestartTimeout, "The server didn't start in time. Please look at server's log file " +
"for more information, or set the value of 'wait' in your config " +
"file to be higher (defaults: 30)."
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/thin/runner.rb
Expand Up @@ -42,7 +42,7 @@ def initialize(argv)
:max_conns => Server::DEFAULT_MAXIMUM_CONNECTIONS,
:max_persistent_conns => Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS,
:require => [],
:wait => Controllers::Cluster::MAXIMUM_WAIT_TIME
:wait => Controllers::Cluster::DEFAULT_WAIT_TIME
}

parse!
Expand Down
32 changes: 32 additions & 0 deletions spec/controllers/cluster_spec.rb
Expand Up @@ -232,4 +232,36 @@ def options_for_port(port)
def options_for_swiftiply(number)
{ :address => '0.0.0.0', :port => 3000, :daemonize => true, :log => "thin.#{number}.log", :timeout => 10, :pid => "thin.#{number}.pid", :chdir => "/rails_app", :swiftiply => true }
end
end

describe Cluster, "rolling restart" do
before do
@cluster = Cluster.new(:chdir => '/rails_app',
:address => '0.0.0.0',
:port => 3000,
:servers => 2,
:timeout => 10,
:log => 'thin.log',
:pid => 'thin.pid',
:onebyone => true,
:wait => 30
)
end

it "should restart servers one by one" do
Command.should_receive(:run).with(:stop, options_for_port(3000))
Command.should_receive(:run).with(:start, options_for_port(3000))
@cluster.should_receive(:wait_until_server_started).with(3000)

Command.should_receive(:run).with(:stop, options_for_port(3001))
Command.should_receive(:run).with(:start, options_for_port(3001))
@cluster.should_receive(:wait_until_server_started).with(3001)

@cluster.restart
end

private
def options_for_port(port)
{ :daemonize => true, :log => "thin.#{port}.log", :timeout => 10, :address => "0.0.0.0", :port => port, :pid => "thin.#{port}.pid", :chdir => "/rails_app" }
end
end

0 comments on commit db14076

Please sign in to comment.