Class: Spring::Client::Run

Inherits:
Command
  • Object
show all
Includes:
RunImpl
Defined in:
lib/spring-jruby/client/run.rb

Constant Summary collapse

TIMEOUT =
RunImpl::TIMEOUT

Constants included from RunImpl

Spring::Client::RunImpl::FORWARDED_SIGNALS

Instance Attribute Summary

Attributes inherited from Command

#args, #env

Instance Method Summary collapse

Methods included from RunImpl

#forward_signal, #forward_signals, #queue_signals, #run_on, #send_std_io_to

Methods inherited from Command

call

Constructor Details

#initialize(args) ⇒ Run



13
14
15
16
# File 'lib/spring-jruby/client/run.rb', line 13

def initialize(args)
  super
  @signal_queue = []
end

Instance Method Details

#boot_serverObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/spring-jruby/client/run.rb', line 67

def boot_server
  env.socket_path.unlink if env.socket_path.exist?

  pid = Process.spawn(
    gem_env,
    "ruby",
    "-e", "gem 'spring-jruby', '#{Spring::VERSION}'; require 'spring-jruby/server'; Spring::Server.boot"
  )

  until env.socket_path.exist?
    _, status = Process.waitpid2(pid, Process::WNOHANG)
    exit status.exitstatus if status
    sleep 0.1
  end
end

#callObject



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/spring-jruby/client/run.rb', line 26

def call
  if env.server_running?
    warm_run
  else
    cold_run
  end
rescue Errno::ECONNRESET
  exit 1
ensure
  server.close if @server
end

#cold_runObject



52
53
54
55
# File 'lib/spring-jruby/client/run.rb', line 52

def cold_run
  boot_server
  run
end

#connect_to_application(client) ⇒ Object



112
113
114
115
116
117
118
119
120
121
# File 'lib/spring-jruby/client/run.rb', line 112

def connect_to_application(client)
  client.forward_to(server)
  send_json server, "args" => args, "default_rails_env" => default_rails_env

  if IO.select([server], [], [], TIMEOUT)
    server.gets or raise CommandNotFound
  else
    raise "Error connecting to Spring server"
  end
end

#default_rails_envObject



162
163
164
# File 'lib/spring-jruby/client/run.rb', line 162

def default_rails_env
  ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
end

#gem_envObject



83
84
85
86
87
88
89
90
91
# File 'lib/spring-jruby/client/run.rb', line 83

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

#kill(sig, pid) ⇒ Object



151
152
153
# File 'lib/spring-jruby/client/run.rb', line 151

def kill(sig, pid)
  Process.kill(sig, -Process.getpgid(pid))
end

#log(message) ⇒ Object



18
19
20
# File 'lib/spring-jruby/client/run.rb', line 18

def log(message)
  env.log "[client] #{message}"
end

#runObject



57
58
59
60
61
62
63
64
65
# File 'lib/spring-jruby/client/run.rb', line 57

def run
  verify_server_version

  application, client = WorkerChannel.pair

  queue_signals
  connect_to_application(client)
  run_command(client, application.to_io)
end

#run_command(client, application) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/spring-jruby/client/run.rb', line 123

def run_command(client, application)
  log "sending command"

  send_std_io_to(application)

  send_json application, "args" => args, "env" => ENV.to_hash

  IO.select([server])
  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}"

    run_on(application, pid)
  else
    log "got no pid"
    exit 1
  end
ensure
  application.close
end

#send_json(socket, data) ⇒ Object



155
156
157
158
159
160
# File 'lib/spring-jruby/client/run.rb', line 155

def send_json(socket, data)
  data = JSON.dump(data)

  socket.puts  data.bytesize
  socket.write data
end

#serverObject



22
23
24
# File 'lib/spring-jruby/client/run.rb', line 22

def server
  @server ||= UNIXSocket.open(env.socket_name)
end

#stop_serverObject



93
94
95
96
97
# File 'lib/spring-jruby/client/run.rb', line 93

def stop_server
  server.close
  @server = nil
  env.stop
end

#verify_server_versionObject



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/spring-jruby/client/run.rb', line 99

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 and the server.\nYou should restart the server and make sure to use the same version.\n\nCLIENT: \#{env.version}, SERVER: \#{server_version}\n"
    exit 1
  end
end

#warm_runObject



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/spring-jruby/client/run.rb', line 38

def warm_run
  run
rescue CommandNotFound
  require "spring-jruby/commands"

  if Spring.command?(args.first)
    # Command installed since spring started
    stop_server
    cold_run
  else
    raise
  end
end