Skip to content

Support rendering components in non-main Ractors - #2732

Open
joelhawksley wants to merge 4 commits into
mainfrom
joelhawksley-ractor-compatibility-follow-ups
Open

joelhawksley wants to merge 4 commits into
mainfrom
joelhawksley-ractor-compatibility-follow-ups

Conversation

@joelhawksley

Copy link
Copy Markdown
Member

Follow-up to #2728. Makes compiled components render in non-main Ractors under Rails' experimental Rails.application.ractorize!.

Changes

  • Define generated render_template_for and slot methods with Ractor.make_shareable procs. Fall back to the plain block when a user-supplied block captures unshareable state.
  • Make CompileCache a shareable, copy-on-write set guarded by a lock.
  • Freeze class-level state read while rendering: identifier, virtual_path, ancestor calls, and the i18n scope. Stop reading @__vc_compiler and class variables on the render path.
  • Add a before_ractorize hook that shares registered_slots and the sidecar i18n backends. It also primes I18n.default_separator, which i18n memoizes in a class ivar that non-main Ractors can't set.
  • Stop capturing preview options in the routes prepend block. That closure blocked ractorize! at boot.
  • Add test/isolated/ractor_test.rb, which boots a production app, calls ractorize!, and renders components in Ractors: templates, inline call, variants, inheritance, slots, collections, content and translations. It skips when the prerequisites are missing, except in the rails_main_head job, where it fails instead.

CI / dependencies

  • Pin the rails-main and rails-main_head appraisals:
    • Rails 7a569bc
    • Rack a9833c8
    • i18n Shopify/i18n@58aa1dc, from Ractor support ruby-i18n/i18n#741
    • rspec-rails main, which has an unreleased fix for frozen default_url_options
  • Compatibility with the newer Rails and i18n:
    • MissingTemplateError handles TemplateDetails::Requested, which no longer exposes locale, formats, variants or handlers.
    • Use I18n.reserved_keys instead of the deprecated I18n::RESERVED_KEYS.
    • Update the Rails main allocation counts.
  • Only the main appraisals were changed. Regenerating the others fails because audition requires Ruby 4.0.

Notes

  • On Ruby 4.0, the Ractor test still skips: Rails reads i18n's @@fallbacks class variable, which non-main Ractors can't read on 4.0. It passes on Ruby head.
  • I didn't add .ractorize! to the sandbox app. It permanently freezes the app, and Rails only supports it in production, while the sandbox runs in test mode.

joelhawksley and others added 4 commits October 19, 2026 14:12
Make ViewComponent compatible with Rails' experimental
Rails.application.ractorize!:

- Define generated render and slot methods with Ractor-shareable procs.
- Make the compile cache shareable (copy-on-write under a lock).
- Freeze class-level state read while rendering (identifier, virtual
  path, ancestor calls, i18n scope) and stop reading the compiler and
  class variables on the render path.
- Share registered slots and sidecar i18n backends in a
  before_ractorize hook.
- Don't capture preview options in the routes prepend block.
- Add an isolated test that ractorizes a production app and renders
  components in non-main Ractors when supported.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9fa9df75-8ce8-4ebf-89d8-a06669026a8f
Pin the rails-main appraisals to Rails, Rack, and i18n revisions that
support Rails.application.ractorize! (i18n: ruby-i18n/i18n#741), and
fail rather than skip the Ractor test in the rails_main_head job.

- Prime I18n.default_separator before ractorizing, since i18n memoizes
  it in a class ivar that non-main Ractors can't set.
- Support Rails main's TemplateDetails::Requested in MissingTemplateError.
- Prefer I18n.reserved_keys over the deprecated I18n::RESERVED_KEYS.
- Pin rspec-rails to main for frozen default_url_options support.
- Update Rails main allocation counts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9fa9df75-8ce8-4ebf-89d8-a06669026a8f
- Route compiled template rendering through an instance helper so
  @current_template is assigned on the component, not lexically in a
  class method.
- Annotate CompileCache's shareable cache and lock with justification.
- Make controller action_methods shareable in the Ractor test, avoiding
  a Ruby head VM crash until Rails does this in before_ractorize.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9fa9df75-8ce8-4ebf-89d8-a06669026a8f
Recent Ruby head aborts when a non-main Ractor reads a frozen Set that
isn't marked shareable, and no longer lets Rails compile ActionView
templates lazily inside Ractors. Share Rails' leftover frozen state after
ractorize! and render the slots/collection/content cases through wrapper
components instead of view templates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9fa9df75-8ce8-4ebf-89d8-a06669026a8f

This branch has not been deployed

No deployments
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