class Reifier::Server
Public Class Methods
new(app, options = {})
click to toggle source
# File lib/reifier/server.rb, line 3 def initialize(app, options = {}) @app = app @options = options end
Public Instance Methods
load_configuration()
click to toggle source
# File lib/reifier/server.rb, line 8 def load_configuration if defined?(Rails) path = Rails.root.join('config/reifier.rb') else path = Dir.pwd + '/reifier.rb' end return unless File.exist?(path) lines = File.read(path).split("\n") lines.each do |line| eval(line) end puts "======= Loaded settings from #{path} =======\n" rescue NoMethodError => e raise UnsupportedOptionError, "Option #{e.name} is not supported from config file" end
start()
click to toggle source
# File lib/reifier/server.rb, line 28 def start server = TCPServer.new(@options[:Host], @options[:Port]) puts "# Ruby version: #{RUBY_VERSION}" puts "# Min threads: #{@options[:MinThreads]}, max threads: #{@options[:MaxThreads]}" puts "# Environment: #{@options[:environment]}" puts "# Master PID: #{Process.pid}" puts "# Listening on tcp://#{server.addr.last}:#{@options[:Port]}" if @options[:Workers] start_clustered(server) else start_single(server) end end
Private Instance Methods
start!(server)
click to toggle source
# File lib/reifier/server.rb, line 98 def start!(server) pool = Concurrent::ThreadPoolExecutor.new( min_threads: @options[:MinThreads], max_threads: @options[:MaxThreads], max_queue: 0, fallback_policy: :caller_runs, ) loop do socket = server.accept socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) Concurrent::Future.new(executor: pool) do begin request = Request.new(socket, @options) response = Response.new(socket) request.handle response.protocol = request.protocol response << @app.call(request.rack_env) response.handle rescue EOFError # nothing, shit happens rescue Exception => e socket.close STDERR.puts ERROR_HEADER STDERR.puts "#{e.class}: #{e}" STDERR.puts e.backtrace STDERR.puts ERROR_FOOTER end end.execute end end
start_clustered(server)
click to toggle source
# File lib/reifier/server.rb, line 51 def start_clustered(server) puts '# Started in clustered mode' child_pids = [] puts '# ================================' puts "# Spinning up #{@options[:Workers].to_i} Workers" @options[:Workers].to_i.times do |i| pid = fork do start!(server) end puts "# Worker #{i} started with pid: #{pid}" child_pids << pid end Signal.trap 'SIGINT' do puts "\n======= Cleaning up #{child_pids.length} Workers =======\n" child_pids.each do |cpid| begin Process.kill(:INT, cpid) rescue Errno::ESRCH end end exit end loop do pid = Process.wait STDERR.puts "Process #{pid} crashed" child_pids.delete(pid) child_pids << spawn_worker(server) end end
start_single(server)
click to toggle source
# File lib/reifier/server.rb, line 46 def start_single(server) puts '# Started in single mode' start!(server) end
threads(min, max)
click to toggle source
# File lib/reifier/server.rb, line 89 def threads(min, max) @options[:MinThreads] = min @options[:MaxThreads] = max end
workers(count)
click to toggle source
# File lib/reifier/server.rb, line 94 def workers(count) @options[:Workers] = count end