Skip to content

Commit 9db0173

Browse files
authored
Merge pull request #754 from Shopify/add-after-environment-load-hook
Add Spring.after_environment_load hook for post-Rails preloading
2 parents 0242d4d + 9402a10 commit 9db0173

4 files changed

Lines changed: 97 additions & 0 deletions

File tree

lib/spring/application.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ def preload
116116

117117
require Spring.application_root_path.join("config", "environment")
118118

119+
invoke_after_environment_load_callbacks
120+
119121
disconnect_database
120122

121123
@preloaded = :success
@@ -300,6 +302,12 @@ def invoke_after_fork_callbacks
300302
end
301303
end
302304

305+
def invoke_after_environment_load_callbacks
306+
Spring.after_environment_load_callbacks.each do |callback|
307+
callback.call
308+
end
309+
end
310+
303311
def loaded_application_features
304312
root = Spring.application_root_path.to_s
305313
$LOADED_FEATURES.select { |f| f.start_with?(root) }

lib/spring/configuration.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def after_fork(&block)
3535
after_fork_callbacks << block
3636
end
3737

38+
def after_environment_load_callbacks
39+
@after_environment_load_callbacks ||= []
40+
end
41+
42+
def after_environment_load(&block)
43+
after_environment_load_callbacks << block
44+
end
45+
3846
def spawn_on_env
3947
@spawn_on_env ||= []
4048
end

test/support/acceptance_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,22 @@ def self.omg
218218
assert_success app.spring_test_command
219219
end
220220

221+
test "app gets reloaded when after_environment_load preloads test_helper" do
222+
File.write(app.spring_config, <<-RUBY.strip_heredoc)
223+
Spring.after_environment_load do
224+
require File.expand_path("../test/test_helper", __dir__)
225+
end
226+
RUBY
227+
228+
assert_success app.spring_test_command
229+
230+
test_helper = app.path("test/test_helper.rb")
231+
File.write(test_helper, test_helper.read + "\nraise 'omg'\n")
232+
233+
app.await_reload
234+
assert_failure app.spring_test_command, stderr: /omg \(RuntimeError\)/, log: /child \d+ shutdown/
235+
end
236+
221237
test "app recovers when a boot-level error is introduced" do
222238
config = app.application_config.read
223239

@@ -531,6 +547,13 @@ def exec_name
531547
assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"
532548
end
533549

550+
test "after environment load callback" do
551+
File.write(app.spring_config, "Spring.after_environment_load { puts '!callback!' }")
552+
553+
assert_success app.spring_test_command, stdout: "!callback!"
554+
refute_output_includes app.spring_test_command, stdout: "!callback!"
555+
end
556+
534557
test "global config file evaluated" do
535558
File.write("#{app.user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
536559
assert_success "bin/rails runner 'puts 2'", stdout: "!callback!\n2"

test/unit/configuration_test.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
require_relative "../helper"
2+
require "spring/configuration"
3+
4+
class ConfigurationTest < ActiveSupport::TestCase
5+
test "after_environment_load_callbacks is empty by default" do
6+
assert_equal [], Spring.after_environment_load_callbacks
7+
end
8+
9+
test "after_environment_load registers a callback" do
10+
callbacks = []
11+
Spring.stub(:after_environment_load_callbacks, callbacks) do
12+
Spring.after_environment_load { true }
13+
end
14+
assert_equal 1, callbacks.size
15+
end
16+
17+
test "after_environment_load accumulates multiple callbacks in order" do
18+
callbacks = []
19+
Spring.stub(:after_environment_load_callbacks, callbacks) do
20+
Spring.after_environment_load { :first }
21+
Spring.after_environment_load { :second }
22+
end
23+
assert_equal [:first, :second], callbacks.map(&:call)
24+
end
25+
26+
test "after_environment_load callbacks are independent from after_fork callbacks" do
27+
env_callbacks = []
28+
fork_callbacks = []
29+
Spring.stub(:after_environment_load_callbacks, env_callbacks) do
30+
Spring.stub(:after_fork_callbacks, fork_callbacks) do
31+
Spring.after_environment_load { true }
32+
end
33+
end
34+
assert_equal 1, env_callbacks.size
35+
assert_equal 0, fork_callbacks.size
36+
end
37+
38+
test "after_fork_callbacks is empty by default" do
39+
assert_equal [], Spring.after_fork_callbacks
40+
end
41+
42+
test "after_fork registers a callback" do
43+
callbacks = []
44+
Spring.stub(:after_fork_callbacks, callbacks) do
45+
Spring.after_fork { true }
46+
end
47+
assert_equal 1, callbacks.size
48+
end
49+
50+
test "after_fork accumulates multiple callbacks in order" do
51+
callbacks = []
52+
Spring.stub(:after_fork_callbacks, callbacks) do
53+
Spring.after_fork { :first }
54+
Spring.after_fork { :second }
55+
end
56+
assert_equal [:first, :second], callbacks.map(&:call)
57+
end
58+
end

0 commit comments

Comments
 (0)