Skip to content

Commit d414b28

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 d414b28

File tree

6 files changed

+36
-12
lines changed

6 files changed

+36
-12
lines changed

lib/spring/application.rb

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

31+
def spawn_env
32+
env = JSON.load(ENV["SPRING_SPAWN_ENV"].dup).map { |key, value| "#{key}=#{value}" }
33+
env.join(", ") if env.any?
34+
end
35+
3136
def app_env
3237
ENV['RAILS_ENV']
3338
end

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+
].compact
21+
"spring app | #{attributes.join(" | ")}"
22+
end
1723

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

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] : []),

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

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

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)