Skip to content

Commit 781c615

Browse files
committed
Run reload in a background thread to keep the server responsive
On large Rails apps (e.g., Bourgeois), reload takes 10-20 seconds. During that time, the server can't process any other requests (model info, route info, associations), causing the editor to freeze. Run reload in a background thread and respond immediately. If another reload arrives while one is in progress, mark that a follow-up reload is needed. When the current reload finishes, it checks the flag and reloads once more to pick up changes that arrived mid-reload. This means N rapid reloads result in at most 2 actual reloads. Related: Shopify/team-ruby-dx#1734
1 parent ca012cd commit 781c615

1 file changed

Lines changed: 19 additions & 9 deletions

File tree

lib/ruby_lsp/ruby_lsp_rails/server.rb

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,25 @@ def execute(request, params)
320320
send_result(run_migrations)
321321
end
322322
when "reload"
323-
with_progress("rails-reload", "Reloading Ruby LSP Rails instance") do
324-
begin
325-
::Rails.application.reloader.reload!
326-
send_result({ success: true })
327-
rescue StandardError => e
328-
log_message(
329-
"Request reload failed with #{e.class}:\n#{e.full_message(highlight: false)}",
330-
)
331-
send_result({ success: false })
323+
# Respond immediately so callers are not blocked while the app reloads.
324+
# Reload runs in a background thread to keep the server responsive to
325+
# other requests (model, route, association, etc.).
326+
# If a reload is already in progress, we mark that another reload is needed.
327+
# When the current reload finishes, it checks the flag and reloads once more
328+
# to pick up any changes that arrived mid-reload. This means N rapid reloads
329+
# result in at most 2 actual reloads (first + one catch-up).
330+
send_result({ success: true })
331+
if @reload_thread&.alive?
332+
@reload_needed = true
333+
else
334+
@reload_thread = Thread.new do
335+
loop do
336+
@reload_needed = false
337+
with_notification_error_handling("reload") do
338+
::Rails.application.reloader.reload!
339+
end
340+
break unless @reload_needed
341+
end
332342
end
333343
end
334344
when "route_location"

0 commit comments

Comments
 (0)