Class: Spring::Server
- Inherits:
-
Object
- Object
- Spring::Server
- Defined in:
- lib/spring/server.rb
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
Class Method Summary collapse
Instance Method Summary collapse
- #application_starting ⇒ Object
- #boot ⇒ Object
-
#ignore_signals ⇒ Object
Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line will kill the server/application.
-
#initialize(env = Env.new) ⇒ Server
constructor
A new instance of Server.
- #log(message) ⇒ Object
- #rails_env_for(args, default_rails_env) ⇒ Object
-
#redirect_output ⇒ Object
We need to redirect STDOUT and STDERR, otherwise the server will keep the original FDs open which would break piping.
- #serve(client) ⇒ Object
- #set_exit_hook ⇒ Object
-
#set_pgid ⇒ Object
Boot the server into the process group of the current session.
- #set_process_title ⇒ Object
- #shutdown ⇒ Object
- #start_server ⇒ Object
- #watch_bundle ⇒ Object
- #write_pidfile ⇒ Object
Constructor Details
#initialize(env = Env.new) ⇒ Server
Returns a new instance of Server.
25 26 27 28 29 30 |
# File 'lib/spring/server.rb', line 25 def initialize(env = Env.new) @env = env @applications = Hash.new { |h, k| h[k] = ApplicationManager.new(self, k) } @pidfile = env.pidfile_path.open('a') @mutex = Mutex.new end |
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
23 24 25 |
# File 'lib/spring/server.rb', line 23 def env @env end |
Class Method Details
.boot ⇒ Object
19 20 21 |
# File 'lib/spring/server.rb', line 19 def self.boot new.boot end |
Instance Method Details
#application_starting ⇒ Object
148 149 150 |
# File 'lib/spring/server.rb', line 148 def application_starting @mutex.synchronize { exit if env.bundle_mtime != @bundle_mtime } end |
#boot ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/spring/server.rb', line 36 def boot Spring.verify_environment write_pidfile set_pgid ignore_signals set_exit_hook set_process_title watch_bundle start_server end |
#ignore_signals ⇒ Object
Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line will kill the server/application.
99 100 101 |
# File 'lib/spring/server.rb', line 99 def ignore_signals IGNORE_SIGNALS.each { |sig| trap(sig, "IGNORE") } end |
#log(message) ⇒ Object
32 33 34 |
# File 'lib/spring/server.rb', line 32 def log() env.log "[server] #{}" end |
#rails_env_for(args, default_rails_env) ⇒ Object
80 81 82 83 84 85 86 87 88 |
# File 'lib/spring/server.rb', line 80 def rails_env_for(args, default_rails_env) command = Spring.command(args.first) if command.respond_to?(:env) env = command.env(args.drop(1)) end env || default_rails_env end |
#redirect_output ⇒ Object
We need to redirect STDOUT and STDERR, otherwise the server will keep the original FDs open which would break piping. (e.g. ‘spring rake -T | grep db` would hang forever because the server would keep the stdout FD open.)
134 135 136 |
# File 'lib/spring/server.rb', line 134 def redirect_output [STDOUT, STDERR].each { |stream| stream.reopen(env.log_file) } end |
#serve(client) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/spring/server.rb', line 57 def serve(client) log "accepted client" client.puts env.version app_client = client.recv_io command = JSON.load(client.read(client.gets.to_i)) args, default_rails_env = command.values_at('args', 'default_rails_env') if Spring.command?(args.first) log "running command #{args.first}" client.puts client.puts @applications[rails_env_for(args, default_rails_env)].run(app_client) else log "command not found #{args.first}" client.close end rescue SocketError => e raise e unless client.eof? ensure redirect_output end |
#set_exit_hook ⇒ Object
103 104 105 106 107 108 |
# File 'lib/spring/server.rb', line 103 def set_exit_hook server_pid = Process.pid # We don't want this hook to run in any forks of the current process at_exit { shutdown if Process.pid == server_pid } end |
#set_pgid ⇒ Object
Boot the server into the process group of the current session. This will cause it to be automatically killed once the session ends (i.e. when the user closes their terminal).
93 94 95 |
# File 'lib/spring/server.rb', line 93 def set_pgid Process.setpgid(0, SID.pgid) end |
#set_process_title ⇒ Object
138 139 140 141 142 |
# File 'lib/spring/server.rb', line 138 def set_process_title ProcessTitleUpdater.run { |distance| "spring server | #{env.app_name} | started #{distance} ago" } end |
#shutdown ⇒ Object
110 111 112 113 114 115 116 117 118 |
# File 'lib/spring/server.rb', line 110 def shutdown @applications.values.each(&:stop) [env.socket_path, env.pidfile_path].each do |path| if path.exist? path.unlink rescue nil end end end |
#start_server ⇒ Object
48 49 50 51 52 53 54 55 |
# File 'lib/spring/server.rb', line 48 def start_server server = UNIXServer.open(env.socket_name) log "started on #{env.socket_name}" rescue Errno::EPERM raise TmpUnwritable.new(env.tmp_path) else loop { serve server.accept } end |
#watch_bundle ⇒ Object
144 145 146 |
# File 'lib/spring/server.rb', line 144 def watch_bundle @bundle_mtime = env.bundle_mtime end |
#write_pidfile ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/spring/server.rb', line 120 def write_pidfile if @pidfile.flock(File::LOCK_EX | File::LOCK_NB) @pidfile.truncate(0) @pidfile.write("#{Process.pid}\n") @pidfile.fsync else exit 1 end end |