Class: Spring::Application
- Inherits:
-
Object
- Object
- Spring::Application
show all
- Includes:
- ApplicationImpl
- Defined in:
- lib/spring-jruby/application.rb
Instance Attribute Summary collapse
Instance Method Summary
collapse
#before_command, #eager_preload, #fork_child, #notify_manager_ready, #receive_streams, #reopen_streams, #reset_streams, #screen_attached?, #screen_move_to_bottom, #wait, #with_pty
Constructor Details
#initialize(manager, original_env) ⇒ Application
Returns a new instance of Application.
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/spring-jruby/application.rb', line 11
def initialize(manager, original_env)
@manager = manager
@original_env = original_env
@spring_env = Env.new
@mutex = Mutex.new
@waiting = Set.new
@preloaded = false
@state = :initialized
@interrupt = IO.pipe
end
|
Instance Attribute Details
#manager ⇒ Object
Returns the value of attribute manager.
9
10
11
|
# File 'lib/spring-jruby/application.rb', line 9
def manager
@manager
end
|
#original_env ⇒ Object
Returns the value of attribute original_env.
9
10
11
|
# File 'lib/spring-jruby/application.rb', line 9
def original_env
@original_env
end
|
#spring_env ⇒ Object
Returns the value of attribute spring_env.
9
10
11
|
# File 'lib/spring-jruby/application.rb', line 9
def spring_env
@spring_env
end
|
#watcher ⇒ Object
Returns the value of attribute watcher.
9
10
11
|
# File 'lib/spring-jruby/application.rb', line 9
def watcher
@watcher
end
|
Instance Method Details
#app_env ⇒ Object
33
34
35
|
# File 'lib/spring-jruby/application.rb', line 33
def app_env
ENV['RAILS_ENV']
end
|
#app_name ⇒ Object
37
38
39
|
# File 'lib/spring-jruby/application.rb', line 37
def app_name
spring_env.app_name
end
|
#connect_database ⇒ Object
248
249
250
|
# File 'lib/spring-jruby/application.rb', line 248
def connect_database
ActiveRecord::Base.establish_connection if active_record_configured?
end
|
#disconnect_database ⇒ Object
244
245
246
|
# File 'lib/spring-jruby/application.rb', line 244
def disconnect_database
ActiveRecord::Base.remove_connection if active_record_configured?
end
|
#exit ⇒ Object
211
212
213
214
215
216
|
# File 'lib/spring-jruby/application.rb', line 211
def exit
state :exiting
manager.shutdown(:RDWR)
exit_if_finished
sleep
end
|
#exit_if_finished ⇒ Object
218
219
220
221
222
|
# File 'lib/spring-jruby/application.rb', line 218
def exit_if_finished
@mutex.synchronize {
Kernel.exit if exiting? && @waiting.empty?
}
end
|
#exiting? ⇒ Boolean
53
54
55
|
# File 'lib/spring-jruby/application.rb', line 53
def exiting?
@state == :exiting
end
|
#initialized? ⇒ Boolean
65
66
67
|
# File 'lib/spring-jruby/application.rb', line 65
def initialized?
@state == :initialized
end
|
#invoke_after_fork_callbacks ⇒ Object
233
234
235
236
237
|
# File 'lib/spring-jruby/application.rb', line 233
def invoke_after_fork_callbacks
Spring.after_fork_callbacks.each do |callback|
callback.call
end
end
|
#loaded_application_features ⇒ Object
239
240
241
242
|
# File 'lib/spring-jruby/application.rb', line 239
def loaded_application_features
root = Spring.application_root_path.to_s
$LOADED_FEATURES.select { |f| f.start_with?(root) }
end
|
#log(message) ⇒ Object
41
42
43
|
# File 'lib/spring-jruby/application.rb', line 41
def log(message)
spring_env.log "[application:#{app_env}] #{message}"
end
|
#preload ⇒ Object
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# File 'lib/spring-jruby/application.rb', line 75
def preload
log "preloading app"
begin
require "spring-jruby/commands"
ensure
start_watcher
end
require Spring.application_root_path.join("config", "application")
Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
ActiveSupport::Dependencies.mechanism = :load
end
require Spring.application_root_path.join("config", "environment")
@original_cache_classes = Rails.application.config.cache_classes
Rails.application.config.cache_classes = false
disconnect_database
@preloaded = :success
rescue Exception => e
@preloaded = :failure
watcher.add e.backtrace.map { |line| line.match(/^(.*)\:\d+\:in /)[1] }
raise e unless initialized?
ensure
watcher.add loaded_application_features
watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
if defined?(Rails) && Rails.application
watcher.add Rails.application.paths["config/initializers"]
watcher.add Rails.application.paths["config/database"]
if secrets_path = Rails.application.paths["config/secrets"]
watcher.add secrets_path
end
end
end
|
#preload_failed? ⇒ Boolean
49
50
51
|
# File 'lib/spring-jruby/application.rb', line 49
def preload_failed?
@preloaded == :failure
end
|
#preloaded? ⇒ Boolean
45
46
47
|
# File 'lib/spring-jruby/application.rb', line 45
def preloaded?
@preloaded
end
|
#print_exception(stream, error) ⇒ Object
271
272
273
274
275
|
# File 'lib/spring-jruby/application.rb', line 271
def print_exception(stream, error)
first, rest = error.backtrace.first, error.backtrace.drop(1)
stream.puts("#{first}: #{error} (#{error.class})")
rest.each { |line| stream.puts("\tfrom #{line}") }
end
|
#run ⇒ Object
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
# File 'lib/spring-jruby/application.rb', line 119
def run
state :running
notify_manager_ready
loop do
IO.select [manager, @interrupt.first]
if terminating? || watcher_stale? || preload_failed?
exit
else
serve IOWrapper.recv_io(manager, UNIXSocket).to_io
end
end
end
|
#serve(client) ⇒ Object
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
# File 'lib/spring-jruby/application.rb', line 134
def serve(client)
child_started = [false]
log "got client"
manager.puts
stdout, stderr, stdin = streams = receive_streams(client)
reopen_streams(streams)
preload unless preloaded?
args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
command = Spring.command(args.shift)
connect_database
setup command
if Rails.application.reloaders.any?(&:updated?)
ActionDispatch::Reloader.cleanup!
ActionDispatch::Reloader.prepare!
end
fork_child(client, streams, child_started) {
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
trap("TERM", "DEFAULT")
ARGV.replace(args)
$0 = command.exec_name
original_env.each { |k, v| ENV.delete k if ENV[k] == v }
env.each { |k, v| ENV[k] ||= v }
if @original_cache_classes
ActiveSupport::Dependencies.mechanism = :require
Rails.application.config.cache_classes = true
end
connect_database
srand
invoke_after_fork_callbacks
shush_backtraces
before_command
command.call
}
rescue Exception => e
Kernel.exit if exiting? && e.is_a?(SystemExit)
log "exception: #{e}"
manager.puts unless child_started[0]
if streams && !e.is_a?(SystemExit)
print_exception(stderr || STDERR, e)
streams.each(&:close)
end
client.puts(1) if child_started[0]
client.close
end
|
#setup(command) ⇒ Object
The command might need to require some files in the main process so that they are cached. For example a test command wants to load the helper file once and have it cached.
227
228
229
230
231
|
# File 'lib/spring-jruby/application.rb', line 227
def setup(command)
if command.setup
watcher.add loaded_application_features
end
end
|
#shush_backtraces ⇒ Object
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
# File 'lib/spring-jruby/application.rb', line 253
def shush_backtraces
Kernel.module_eval do
old_raise = Kernel.method(:raise)
remove_method :raise
define_method :raise do |*args|
begin
old_raise.call(*args)
ensure
if $!
lib = File.expand_path("..", __FILE__)
$!.backtrace.reject! { |line| line.start_with?(lib) }
end
end
end
private :raise
end
end
|
#start_watcher ⇒ Object
69
70
71
72
73
|
# File 'lib/spring-jruby/application.rb', line 69
def start_watcher
@watcher = Spring.watcher
@watcher.on_stale { state! :watcher_stale }
@watcher.start
end
|
#state(val) ⇒ Object
22
23
24
25
26
|
# File 'lib/spring-jruby/application.rb', line 22
def state(val)
return if exiting?
log "#{@state} -> #{val}"
@state = val
end
|
#state!(val) ⇒ Object
28
29
30
31
|
# File 'lib/spring-jruby/application.rb', line 28
def state!(val)
state val
@interrupt.last.write "."
end
|
#terminate ⇒ Object
200
201
202
203
204
205
206
207
208
209
|
# File 'lib/spring-jruby/application.rb', line 200
def terminate
if exiting?
log "forced exit"
@waiting.each { |pid| Process.kill("TERM", pid) }
Kernel.exit
else
state! :terminating
end
end
|
#terminating? ⇒ Boolean
57
58
59
|
# File 'lib/spring-jruby/application.rb', line 57
def terminating?
@state == :terminating
end
|
#watcher_stale? ⇒ Boolean
61
62
63
|
# File 'lib/spring-jruby/application.rb', line 61
def watcher_stale?
@state == :watcher_stale
end
|