Skip to content

Run reload in a background thread to keep the server responsive#692

Draft
KaanOzkan wants to merge 1 commit intoko/reload-returns-resultfrom
ko/async-reload
Draft

Run reload in a background thread to keep the server responsive#692
KaanOzkan wants to merge 1 commit intoko/reload-returns-resultfrom
ko/async-reload

Conversation

@KaanOzkan
Copy link
Contributor

@KaanOzkan KaanOzkan commented Mar 6, 2026

Summary

On large Rails apps, Rails.application.reloader.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 completely.

This PR runs reload in a background thread and responds to the caller immediately. If another reload request arrives while one is already in progress, it's skipped — the running reload will pick up all file changes anyway (that's how Rails reloader works).

Depends on #691 (reload returns result).

How it works

when "reload"
  if @reload_thread&.alive?
    send_result({ success: true, skipped: true })  # dedup
  else
    send_result({ success: true })                  # respond immediately
    @reload_thread = Thread.new do
      ::Rails.application.reloader.reload!           # reload in background
    end
  end

Trade-off

DSL generation may run against slightly stale state if it starts before the background reload finishes. This is mitigated by the companion Tapioca fix (Don't delete RBIs for missing constants) which preserves existing RBIs when constants are temporarily unavailable.

Testing

Unit tests:

  • RED: With a monkey-patched 2s reload, execute("reload") blocked for 2.04s
  • GREEN: Same test returns in <0.5s
  • Duplicate reload while first is running → skipped (only 1 actual reload! call)

End-to-end with real Rails runner:

  • trigger_reload responds instantly
  • Model requests work immediately after reload
  • 5 rapid reloads handled in 0.001s
  • Server remains responsive throughout

All 45 existing tests pass.

Related

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant