Class: Thin::Controllers::Cluster

Inherits:
Controller show all
Defined in:
lib/thin/controllers/cluster.rb

Overview

Control a set of servers.

  • Generate start and stop commands and run them.

  • Inject the port or socket number in the pid and log filenames.

Servers are started throught the thin command-line script.

Constant Summary collapse

CLUSTER_OPTIONS =

Cluster only options that should not be passed in the command sent to the indiviual servers.

[:servers, :only, :onebyone, :wait]
DEFAULT_WAIT_TIME =

Maximum wait time for the server to be restarted

30

Instance Attribute Summary

Attributes inherited from Controller

#options

Instance Method Summary collapse

Methods inherited from Controller

#config

Methods included from Logging

#debug, debug, debug?, #log, log, #log_error, log_error, #silent, #silent=, silent?, #trace, trace, trace?

Constructor Details

#initialize(options) ⇒ Cluster

Create a new cluster of servers launched using options.



21
22
23
24
25
# File 'lib/thin/controllers/cluster.rb', line 21

def initialize(options)
  super
  # Cluster can only contain daemonized servers
  @options.merge!(:daemonize => true)
end

Instance Method Details

#addressObject



28
# File 'lib/thin/controllers/cluster.rb', line 28

def address;    @options[:address]  end

#first_portObject



27
# File 'lib/thin/controllers/cluster.rb', line 27

def first_port; @options[:port]     end

#log_fileObject



31
# File 'lib/thin/controllers/cluster.rb', line 31

def log_file;   @options[:log]      end

#log_file_for(number) ⇒ Object



123
124
125
# File 'lib/thin/controllers/cluster.rb', line 123

def log_file_for(number)
  include_server_number log_file, number
end

#onebyoneObject



34
# File 'lib/thin/controllers/cluster.rb', line 34

def onebyone;   @options[:onebyone] end

#onlyObject



33
# File 'lib/thin/controllers/cluster.rb', line 33

def only;       @options[:only]     end

#pid_fileObject



30
# File 'lib/thin/controllers/cluster.rb', line 30

def pid_file;   @options[:pid]      end

#pid_file_for(number) ⇒ Object



127
128
129
# File 'lib/thin/controllers/cluster.rb', line 127

def pid_file_for(number)
  include_server_number pid_file, number
end

#pid_for(number) ⇒ Object



135
136
137
# File 'lib/thin/controllers/cluster.rb', line 135

def pid_for(number)
  File.read(pid_file_for(number)).chomp.to_i
end

#restartObject

Stop and start the servers.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/thin/controllers/cluster.rb', line 66

def restart
  unless onebyone
    # Let's do a normal restart by defaults
    stop
    sleep 0.1 # Let's breath a bit shall we ?
    start
  else
    with_each_server do |n|
      stop_server(n)
      sleep 0.1 # Let's breath a bit shall we ?
      start_server(n)
      wait_until_server_started(n)
    end
  end
end

#server_id(number) ⇒ Object



113
114
115
116
117
118
119
120
121
# File 'lib/thin/controllers/cluster.rb', line 113

def server_id(number)
  if socket
    socket_for(number)
  elsif swiftiply?
    [address, first_port, number].join(':')
  else
    [address, number].join(':')
  end
end

#sizeObject



32
# File 'lib/thin/controllers/cluster.rb', line 32

def size;       @options[:servers]  end

#socketObject



29
# File 'lib/thin/controllers/cluster.rb', line 29

def socket;     @options[:socket]   end

#socket_for(number) ⇒ Object



131
132
133
# File 'lib/thin/controllers/cluster.rb', line 131

def socket_for(number)
  include_server_number socket, number
end

#startObject

Start the servers



42
43
44
# File 'lib/thin/controllers/cluster.rb', line 42

def start
  with_each_server { |n| start_server n }
end

#start_server(number) ⇒ Object

Start a single server



47
48
49
50
51
# File 'lib/thin/controllers/cluster.rb', line 47

def start_server(number)
  log "Starting server on #{server_id(number)} ... "

  run :start, number
end

#stopObject

Stop the servers



54
55
56
# File 'lib/thin/controllers/cluster.rb', line 54

def stop
  with_each_server { |n| stop_server n }
end

#stop_server(number) ⇒ Object

Stop a single server



59
60
61
62
63
# File 'lib/thin/controllers/cluster.rb', line 59

def stop_server(number)
  log "Stopping server on #{server_id(number)} ... "

  run :stop, number
end

#swiftiply?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/thin/controllers/cluster.rb', line 37

def swiftiply?
  @options.has_key?(:swiftiply)
end

#test_socket(number) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'lib/thin/controllers/cluster.rb', line 82

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

#waitObject



35
# File 'lib/thin/controllers/cluster.rb', line 35

def wait;       @options[:wait]     end

#wait_until_server_started(number) ⇒ Object

Make sure the server is running before moving on to the next one.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/thin/controllers/cluster.rb', line 93

def wait_until_server_started(number)
  log "Waiting for server to start ..."
  STDOUT.flush # Need this to make sure user got the message

  tries = 0
  loop do
    if test_socket = test_socket(number)
      test_socket.close
      break
    elsif tries < wait
      sleep 1
      tries += 1
    else
      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