spring 4.4.2 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: def7b2369b2bfd2e89227a11ab9fab2a336b10011ec8b51a82319828e73ecee4
4
- data.tar.gz: 58e3868998fe06b76e2e6a86cd5274aabdd5f315395aae004e5cfd3d488708ca
3
+ metadata.gz: f386aff68c6b8feab1d79a933df930e6c47bf8d2f5f3610c7c483954e1b97cff
4
+ data.tar.gz: fb1ef130a243970266279570dad57c259ecd828cfab6b1043482ed429234e363
5
5
  SHA512:
6
- metadata.gz: 4e48694be64ae52918a2a82c61d5e0ba1bec2c826123b697e789abcf74c38d7d8d6162b32b64ccd8694855e2bb4cf29af5147a2ea34fd96163c95fd4405940c7
7
- data.tar.gz: '054845db5469efb81a6fc0a9775dcbaa0518153e51a13807a2e340a470b5ac100cd01f51f99b9676ccae1b395fd2b57bb3306d65410f1587999481ed40052d80'
6
+ metadata.gz: da2a3fbbb088ca721ed27128e0a60be6b8946b519ae4580fb7c99cc76f3052063b24bbacce932db0212a9308094e1e392e7a7c6937526dc19d940c896c4c4a1d
7
+ data.tar.gz: d712161465b1217b783046ec10ad2694c65bf7897ab78cc7e97d1b6c33ae0a124dc949f9dd056755d5aaf40890c502ee617e3ad2338cbe8551731ae8c29b1774
data/README.md CHANGED
@@ -79,6 +79,31 @@ Spring manages. That setting is typically configured in
79
79
  Note: in versions of Rails before 7.1, the setting is called `cache_classes`,
80
80
  and it needs to be `false` for Spring to work.
81
81
 
82
+ #### Running Spring with reloading disabled (advanced, risky)
83
+
84
+ If you know what you are doing, and if every reloadable resource is configured
85
+ to materialize *lazily in the forked child*, not in the Spring server process,
86
+ then you can decide to run Spring without Rail's in-process reloaders.
87
+
88
+ To opt into this, set in `config/spring.rb`:
89
+
90
+ ```ruby
91
+ Spring.dangerously_allow_disabling_reloading = true
92
+ ```
93
+
94
+ If you set this, you should make sure that you are NOT pre-loading reloadable
95
+ resource in the Spring server. One approach is to add boot-time assertions at
96
+ the end of `Spring.after_environment_load`, e.g.:
97
+
98
+ ```ruby
99
+ Spring.after_environment_load do
100
+ raise "routes were drawn at boot" if Rails.application.routes_reloader.loaded
101
+ raise "i18n locales where loaded at boot" unless I18n.backend.instance_variable_get(:@translations).nil?
102
+ end
103
+ ```
104
+
105
+ When unsure, leave this disabled.
106
+
82
107
  ### Usage
83
108
 
84
109
  For this walkthrough I've generated a new Rails application, and run
@@ -334,7 +359,8 @@ server process is started, it can be used to add new top-level commands.
334
359
  Spring must know how to find your Rails application. If you have a
335
360
  normal app everything works out of the box. If you are working on a
336
361
  project with a special setup (an engine for example), you must tell
337
- Spring where your app is located:
362
+ Spring where your app is located by specifying the below code in a
363
+ `config/spring.rb` file relative to your engines root directory :
338
364
 
339
365
  ```ruby
340
366
  Spring.application_root = './test/dummy'
@@ -101,6 +101,8 @@ module Spring
101
101
  end
102
102
 
103
103
  Rails::Application.initializer :ensure_reloading_is_enabled, group: :all do
104
+ next if Spring.dangerously_allow_disabling_reloading
105
+
104
106
  if Rails.application.config.cache_classes
105
107
  config_name, set_to = if Rails.application.config.respond_to?(:enable_reloading=)
106
108
  ["enable_reloading", "true"]
@@ -110,12 +112,17 @@ module Spring
110
112
  raise <<-MSG.strip_heredoc
111
113
  Spring reloads, and therefore needs the application to have reloading enabled.
112
114
  Please, set config.#{config_name} to #{set_to} in config/environments/#{Rails.env}.rb.
115
+ (If you understand the trade-offs and want to disable Rails' reloader anyway,
116
+ set `Spring.dangerously_allow_disabling_reloading = true` in config/spring.rb.)
113
117
  MSG
114
118
  end
115
119
  end
116
120
 
117
121
  require Spring.application_root_path.join("config", "environment")
118
122
 
123
+ invoke_after_environment_load_callbacks
124
+ preload_framework_base_classes
125
+
119
126
  disconnect_database
120
127
 
121
128
  @preloaded = :success
@@ -142,6 +149,19 @@ module Spring
142
149
  end
143
150
  end
144
151
 
152
+ # Eagerly autoload framework base classes
153
+ FRAMEWORK_BASE_CLASSES = %w[
154
+ ActionMailer::Base
155
+ ActionController::Base
156
+ ActionController::API
157
+ ].freeze
158
+
159
+ def preload_framework_base_classes
160
+ FRAMEWORK_BASE_CLASSES.each do |const|
161
+ Object.const_get(const) if Object.const_defined?(const)
162
+ end
163
+ end
164
+
145
165
  def eager_preload
146
166
  with_pty do
147
167
  # we can't see stderr and there could be issues when it's overflown
@@ -183,7 +203,7 @@ module Spring
183
203
  client.puts(0) # preload success
184
204
  rescue Exception
185
205
  log "preload failed"
186
- client.puts(1) # preload failure
206
+ ignore_client_disconnect { client.puts(1) } # preload failure
187
207
  raise
188
208
  end
189
209
  end
@@ -244,15 +264,19 @@ module Spring
244
264
 
245
265
  wait pid, streams, client
246
266
  rescue Exception => e
247
- log "exception: #{e}"
267
+ if e.is_a?(Errno::EPIPE)
268
+ log "client disconnected (#{e.message}), ignoring command"
269
+ else
270
+ log "exception: #{e}"
271
+ end
248
272
  manager.puts unless pid
249
273
 
250
274
  if streams && !e.is_a?(SystemExit)
251
- print_exception(stderr, e)
252
- streams.each(&:close)
275
+ ignore_client_disconnect { print_exception(stderr, e) }
276
+ streams.each { |stream| ignore_client_disconnect { stream.close } }
253
277
  end
254
278
 
255
- client.puts(1) if pid
279
+ ignore_client_disconnect { client.puts(1) if pid }
256
280
  client.close
257
281
  ensure
258
282
  # Redirect STDOUT and STDERR to prevent from keeping the original FDs
@@ -300,6 +324,12 @@ module Spring
300
324
  end
301
325
  end
302
326
 
327
+ def invoke_after_environment_load_callbacks
328
+ Spring.after_environment_load_callbacks.each do |callback|
329
+ callback.call
330
+ end
331
+ end
332
+
303
333
  def loaded_application_features
304
334
  root = Spring.application_root_path.to_s
305
335
  $LOADED_FEATURES.select { |f| f.start_with?(root) }
@@ -403,6 +433,15 @@ module Spring
403
433
 
404
434
  private
405
435
 
436
+ # Tolerate Errno::EPIPE on writes to the client socket. Once the client
437
+ # disconnects, every subsequent write to it raises — that's expected
438
+ # during `serve`'s status reporting; we'd be talking to a process
439
+ # that's gone.
440
+ def ignore_client_disconnect
441
+ yield
442
+ rescue Errno::EPIPE
443
+ end
444
+
406
445
  def active_record_configured?
407
446
  defined?(ActiveRecord::Base) && ActiveRecord::Base.configurations.any?
408
447
  end
@@ -26,7 +26,7 @@ module Spring
26
26
  if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
27
27
  require "bundler"
28
28
 
29
- Bundler.locked_gems.specs.find { |spec| spec.name == "spring" }&.tap do |spring|
29
+ Bundler.definition.requested_specs.find { |spec| spec.name == "spring" }&.tap do |spring|
30
30
  Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
31
31
  gem "spring", spring.version
32
32
  require "spring/binstub"
@@ -3,11 +3,17 @@ require "spring/errors"
3
3
  module Spring
4
4
  @connect_timeout = 5
5
5
  @boot_timeout = 20
6
+ @dangerously_allow_disabling_reloading = false
6
7
 
7
8
  class << self
8
9
  attr_accessor :application_root, :connect_timeout, :boot_timeout
9
10
  attr_writer :quiet
10
11
 
12
+ # Opt-in: skip the `:ensure_reloading_is_enabled` initializer so Spring
13
+ # boots with `config.enable_reloading = false`. Default `false`. See
14
+ # README "Running Spring with reloading disabled" for what this gives up.
15
+ attr_accessor :dangerously_allow_disabling_reloading
16
+
11
17
  def gemfile
12
18
  require "bundler"
13
19
 
@@ -35,6 +41,14 @@ module Spring
35
41
  after_fork_callbacks << block
36
42
  end
37
43
 
44
+ def after_environment_load_callbacks
45
+ @after_environment_load_callbacks ||= []
46
+ end
47
+
48
+ def after_environment_load(&block)
49
+ after_environment_load_callbacks << block
50
+ end
51
+
38
52
  def spawn_on_env
39
53
  @spawn_on_env ||= []
40
54
  end
data/lib/spring/server.rb CHANGED
@@ -74,6 +74,8 @@ module Spring
74
74
  end
75
75
  rescue SocketError => e
76
76
  raise e unless client.eof?
77
+ rescue Errno::EPIPE => e
78
+ log "client disconnected with error #{e.message}, ignoring command"
77
79
  ensure
78
80
  redirect_output
79
81
  end
@@ -1,3 +1,3 @@
1
1
  module Spring
2
- VERSION = "4.4.2"
2
+ VERSION = "4.6.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spring
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.2
4
+ version: 4.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton