Skip to content

Commit b5f86ef

Browse files
committed
Add Spring.spawn_on_env
Currently, the only way Spring can create multiple applications for a given environment variable value is by changing the `SPRING_APPLICATION_ID`. This has the tradeoff of not being visible in `bin/spring status` calls, and being treated as a separate application, when it actually isn't. You might want to run an application with and without certain features enabled in the same rails env, and with this patch you can do that and have Spring treat these as the same app. Configuration must be set in config/spring_client.rb
1 parent 8b285d5 commit b5f86ef

File tree

6 files changed

+35
-12
lines changed

6 files changed

+35
-12
lines changed

Diff for: lib/spring/application.rb

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ def state!(val)
2828
@interrupt.last.write "."
2929
end
3030

31+
def spawn_env
32+
JSON.load(ENV["SPRING_SPAWN_ENV"].dup).map { |key, value| "#{key}=#{value}" }.join(", ")
33+
end
34+
3135
def app_env
3236
ENV['RAILS_ENV']
3337
end

Diff for: lib/spring/application/boot.rb

+9-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111

1212
Signal.trap("TERM") { app.terminate }
1313

14-
Spring::ProcessTitleUpdater.run { |distance|
15-
"spring app | #{app.app_name} | started #{distance} ago | #{app.app_env} mode"
16-
}
14+
Spring::ProcessTitleUpdater.run do |distance|
15+
attributes = [
16+
app.app_name,
17+
"started #{distance} ago",
18+
"#{app.app_env} mode",
19+
app.spawn_env,
20+
]
21+
"spring app | #{attributes.join(" | ")}"
22+
end
1723

1824
app.eager_preload if ENV.delete("SPRING_PRELOAD") == "1"
1925
app.run

Diff for: lib/spring/application_manager.rb

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
module Spring
22
class ApplicationManager
3-
attr_reader :pid, :child, :app_env, :spring_env, :status
3+
attr_reader :pid, :child, :app_env, :spawn_env, :spring_env, :status
44

5-
def initialize(app_env, spring_env)
5+
def initialize(app_env, spawn_env, spring_env)
66
@app_env = app_env
7+
@spawn_env = spawn_env
78
@spring_env = spring_env
89
@mutex = Mutex.new
910
@state = :running
@@ -100,7 +101,9 @@ def start_child(preload = false)
100101
"RAILS_ENV" => app_env,
101102
"RACK_ENV" => app_env,
102103
"SPRING_ORIGINAL_ENV" => JSON.dump(Spring::ORIGINAL_ENV),
103-
"SPRING_PRELOAD" => preload ? "1" : "0"
104+
"SPRING_PRELOAD" => preload ? "1" : "0",
105+
"SPRING_SPAWN_ENV" => JSON.dump(spawn_env),
106+
**spawn_env,
104107
},
105108
"ruby",
106109
*(bundler_dir != RbConfig::CONFIG["rubylibdir"] ? ["-I", bundler_dir] : []),

Diff for: lib/spring/client/run.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def verify_server_version
132132

133133
def connect_to_application(client)
134134
server.send_io client
135-
send_json server, "args" => args, "default_rails_env" => default_rails_env
135+
send_json server, "args" => args, "default_rails_env" => default_rails_env, "spawn_env" => spawn_env
136136

137137
if IO.select([server], [], [], CONNECT_TIMEOUT)
138138
server.gets or raise CommandNotFound
@@ -232,6 +232,10 @@ def send_json(socket, data)
232232
def default_rails_env
233233
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
234234
end
235+
236+
def spawn_env
237+
ENV.slice(*Spring.spawn_on_env)
238+
end
235239
end
236240
end
237241
end

Diff for: lib/spring/configuration.rb

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ def after_fork(&block)
3232
after_fork_callbacks << block
3333
end
3434

35+
def spawn_on_env
36+
@spawn_on_env ||= []
37+
end
38+
3539
def verify_environment
3640
application_root_path
3741
end

Diff for: lib/spring/server.rb

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ def self.boot(options = {})
1919
def initialize(options = {})
2020
@foreground = options.fetch(:foreground, false)
2121
@env = options[:env] || default_env
22-
@applications = Hash.new { |h, k| h[k] = ApplicationManager.new(k, env) }
22+
@applications = Hash.new do |hash, key|
23+
hash[key] = ApplicationManager.new(*key, env)
24+
end
2325
@pidfile = env.pidfile_path.open('a')
2426
@mutex = Mutex.new
2527
end
@@ -57,12 +59,12 @@ def serve(client)
5759
app_client = client.recv_io
5860
command = JSON.load(client.read(client.gets.to_i))
5961

60-
args, default_rails_env = command.values_at('args', 'default_rails_env')
62+
args, default_rails_env, spawn_env = command.values_at('args', 'default_rails_env', 'spawn_env')
6163

6264
if Spring.command?(args.first)
6365
log "running command #{args.first}"
6466
client.puts
65-
client.puts @applications[rails_env_for(args, default_rails_env)].run(app_client)
67+
client.puts @applications[rails_env_for(args, default_rails_env, spawn_env)].run(app_client)
6668
else
6769
log "command not found #{args.first}"
6870
client.close
@@ -73,8 +75,8 @@ def serve(client)
7375
redirect_output
7476
end
7577

76-
def rails_env_for(args, default_rails_env)
77-
Spring.command(args.first).env(args.drop(1)) || default_rails_env
78+
def rails_env_for(args, default_rails_env, spawn_env)
79+
[Spring.command(args.first).env(args.drop(1)) || default_rails_env, spawn_env]
7880
end
7981

8082
# Boot the server into the process group of the current session.

0 commit comments

Comments
 (0)