lib/yarn/server.rb in yarn-0.1.0 vs lib/yarn/server.rb in yarn-0.1.1
- old
+ new
@@ -1,8 +1,10 @@
require 'socket'
+# Yarn namespace
module Yarn
+ # The heart of Yarn which starts a TCP server and forks workers which handles requests.
class Server
include Logging
include Socket::Constants
@@ -15,10 +17,11 @@
# set maximum number of
]
attr_accessor :host, :port, :socket, :workers
+ # Initializes a new Server with the given options Hash.
def initialize(options={})
# merge given options with default values
opts = {
output: $stdout,
host: '127.0.0.1',
@@ -26,30 +29,32 @@
workers: 4,
log: true,
rack: "off"
}.merge(options)
- @app = nil
- @app = load_rack_app(opts[:rack]) unless opts[:rack] == "off"
+ @app = opts[:rack] == "off" ? nil : load_rack_app(opts[:rack])
@opts = opts
@host, @port, @num_workers = opts[:host], opts[:port], opts[:workers]
@workers = []
$output, $debug = opts[:output], opts[:debug]
$log = opts[:log] || opts[:debug]
end
+ # Loads a Rack application from a given file path.
+ # If the file does not exist, the program exits.
def load_rack_app(app_path)
if File.exists?(app_path)
config_file = File.read(app_path)
- rack_application = eval("Rack::Builder.new { #{config_file} }")
+ rack_application = eval("Rack::Builder.new { #{config_file} }.to_app", TOPLEVEL_BINDING, app_path)
else
log "#{app_path} does not exist. Exiting."
Kernel::exit
end
end
+ # Creates a new TCPServer and invokes init_workers
def start
trap("INT") { stop }
@socket = TCPServer.new(@host, @port)
@socket.listen(1024)
::BasicSocket.do_not_reverse_lookup=true
@@ -59,35 +64,43 @@
# Waits here for all processes to exit
Process.waitall
end
+ # Applies TCP optimizations to the TCP socket
def configure_socket
TCP_OPTS.each { |opt| @session.setsockopt(*opt) }
end
+ # Runs fork_worker @num_worker times
def init_workers
@num_workers.times { @workers << fork_worker }
end
+ # Forks a new process with a worker
def fork_worker
fork { worker }
end
+ # Contains the logic performed by each worker. It first determines the
+ # handler type and then start an infinite loop listening for incomming
+ # requests. Upon receiving a request, it fires the run method on the handler.
def worker
trap("INT") { exit }
handler = get_handler
loop do
@session = @socket.accept
configure_socket
handler.run @session
end
end
+ # Returns the handler corresponding to whether a Rack application is present.
def get_handler
@app ? RackHandler.new(@app,@opts) : RequestHandler.new
end
+ # Closes the TCPServer and exits with a message.
def stop
@socket.close if (@socket && !@socket.closed?)
log "Server stopped. Have a nice day!"
end