class Spring::Client::Run
Constants
- BOOT_TIMEOUT
- CONNECT_TIMEOUT
- FORWARDED_SIGNALS
Attributes
Public Class Methods
Source
# File lib/spring/client/run.rb, line 14 def initialize(args) super @signal_queue = [] @server_booted = false end
Calls superclass method
Spring::Client::Command::new
Public Instance Methods
Source
# File lib/spring/client/run.rb, line 73 def boot_server env.socket_path.unlink if env.socket_path.exist? pid = Process.spawn(gem_env, env.server_command, out: File::NULL) timeout = Time.now + BOOT_TIMEOUT @server_booted = true until env.socket_path.exist? _, status = Process.waitpid2(pid, Process::WNOHANG) if status exit status.exitstatus elsif Time.now > timeout $stderr.puts "Starting Spring server with `#{env.server_command}` " \ "timed out after #{BOOT_TIMEOUT} seconds" exit 1 end sleep 0.1 end end
Source
# File lib/spring/client/run.rb, line 29 def call begin connect rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED cold_run else warm_run end ensure server.close if server end
Source
# File lib/spring/client/run.rb, line 55 def cold_run boot_server connect run end
Source
# File lib/spring/client/run.rb, line 25 def connect @server = UNIXSocket.open(env.socket_name) end
Source
# File lib/spring/client/run.rb, line 133 def connect_to_application(client) server.send_io client send_json server, "args" => args, "default_rails_env" => default_rails_env if IO.select([server], [], [], CONNECT_TIMEOUT) server.gets or raise CommandNotFound else raise "Error connecting to Spring server" end end
Source
# File lib/spring/client/run.rb, line 232 def default_rails_env ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development' end
Source
# File lib/spring/client/run.rb, line 211 def forward_signal(sig, application) if kill(sig, application) != 0 # If the application process is gone, then don't block the # signal on this process. trap(sig, 'DEFAULT') Process.kill(sig, Process.pid) end end
Source
# File lib/spring/client/run.rb, line 203 def forward_signals(application) @signal_queue.each { |sig| kill sig, application } FORWARDED_SIGNALS.each do |sig| trap(sig) { forward_signal sig, application } end end
Source
# File lib/spring/client/run.rb, line 100 def gem_env bundle = Bundler.bundle_path.to_s paths = Gem.path + ENV["GEM_PATH"].to_s.split(File::PATH_SEPARATOR) { "GEM_PATH" => [bundle, *paths].uniq.join(File::PATH_SEPARATOR), "GEM_HOME" => bundle } end
Source
# File lib/spring/client/run.rb, line 220 def kill(sig, application) application.puts(sig) application.gets.to_i end
Source
# File lib/spring/client/run.rb, line 21 def log(message) env.log "[client] #{message}" end
Source
# File lib/spring/client/run.rb, line 185 def queue_signals FORWARDED_SIGNALS.each do |sig| trap(sig) { @signal_queue << sig } end end
Source
# File lib/spring/client/run.rb, line 61 def run verify_server_version application, client = UNIXSocket.pair queue_signals connect_to_application(client) run_command(client, application) rescue Errno::ECONNRESET exit 1 end
Source
# File lib/spring/client/run.rb, line 144 def run_command(client, application) application.send_io STDOUT application.send_io STDERR application.send_io STDIN log "waiting for the application to be preloaded" preload_status = application.gets preload_status = preload_status.chomp if preload_status log "app preload status: #{preload_status}" exit 1 if preload_status == "1" log "sending command" send_json application, "args" => args, "env" => ENV.to_hash pid = server.gets pid = pid.chomp if pid # We must not close the client socket until we are sure that the application has # received the FD. Otherwise the FD can end up getting closed while it's in the server # socket buffer on OS X. This doesn't happen on Linux. client.close if pid && !pid.empty? log "got pid: #{pid}" suspend_resume_on_tstp_cont(pid) forward_signals(application) status = application.read.to_i log "got exit status #{status}" exit status else log "got no pid" exit 1 end ensure application.close end
Source
# File lib/spring/client/run.rb, line 225 def send_json(socket, data) data = JSON.dump(data) socket.puts data.bytesize socket.write data end
Source
# File lib/spring/client/run.rb, line 96 def server_booted? @server_booted end
Source
# File lib/spring/client/run.rb, line 110 def stop_server server.close @server = nil env.stop end
Source
# File lib/spring/client/run.rb, line 191 def suspend_resume_on_tstp_cont(pid) trap("TSTP") { log "suspended" Process.kill("STOP", pid.to_i) Process.kill("STOP", Process.pid) } trap("CONT") { log "resumed" Process.kill("CONT", pid.to_i) } end
Source
# File lib/spring/client/run.rb, line 116 def verify_server_version server_version = server.gets.chomp if server_version != env.version $stderr.puts "There is a version mismatch between the Spring client " \ "(#{env.version}) and the server (#{server_version})." if server_booted? $stderr.puts "We already tried to reboot the server, but the mismatch is still present." exit 1 else $stderr.puts "Restarting to resolve." stop_server cold_run end end end
Source
# File lib/spring/client/run.rb, line 41 def warm_run run rescue CommandNotFound require "spring/commands" if Spring.command?(args.first) # Command installed since Spring started stop_server cold_run else raise end end