Add ActiveSupport::Ractors.try_make_shareable
Rails now provides ActiveSupport::Ractors.try_make_shareable, a helper that attempts to make arbitrary objects Ractor‑shareable while letting applications choose how isolation errors are handled.
背景
Ractor safety has been a recurring requirement for Rails core and applications alike, especially when objects other than procs cross thread‑like boundaries. Existing support focused on procs via try_shareable_proc, but many code paths still raise Ractor::IsolationError when non‑shareable objects are encountered. The PR addresses this gap by introducing a generic mechanism that respects the existing configuration flag unshareable_proc_action.
This change prepares Rails for broader Ractor adoption without breaking existing behaviour, matching the motivation described in the related PR #57626.
技術的な変更
The core addition lives in activesupport/lib/active_support/ractors.rb, where a new method try_make_shareable is defined. The method returns the original object when unshareable_proc_action is falsy, otherwise it delegates to make_shareable and rescues Ractor::IsolationError.
def try_make_shareable(obj)
return obj unless unshareable_proc_action
make_shareable(obj)
rescue Ractor::IsolationError
case unshareable_proc_action
when :raise
raise
when :warn
ActiveSupport.deprecator.warn(<<~MSG)
Rails attempted to make an object from your application Ractor shareable but a Ractor
Isolation error was raised. The object being returned is not Ractor safe and a runtime
error may occur anytime during the request lifecycle.
#{obj.inspect}
MSG
obj
end
end
The corresponding test suite activesupport/test/ractors_test.rb adds several cases to verify behaviour under nil, :raise, and :warn settings. For example, when unshareable_proc_action is :raise, the method raises Ractor::IsolationError for an unshareable proc, while :warn emits a deprecation warning and returns the original object.
def test_try_make_shareable_when_action_is_nil
old = ActiveSupport::Ractors.unshareable_proc_action
ActiveSupport::Ractors.unshareable_proc_action = nil
obj = +"hello"
attempted = ActiveSupport::Ractors.try_make_shareable(obj)
assert_same(obj, attempted)
assert_not ActiveSupport::Ractors.shareable?(obj)
ensure
ActiveSupport::Ractors.unshareable_proc_action = old
end
These additions are isolated to the ActiveSupport::Ractors module; no other files are modified.
設計判断
The implementation extends the existing unshareable_proc_action flag rather than introducing a new configuration key. This decision preserves backward compatibility and keeps the developer‑facing API surface minimal, as discussed in the PR description.
By handling the three possible values (:raise, :warn, nil) within a single method, the design centralises Ractor‑shareability logic and avoids scattering error‑handling code across multiple callers. The :warn path leverages ActiveSupport.deprecator.warn, integrating with Rails' standard deprecation infrastructure.
Choosing to raise, warn, or silently ignore aligns with the established behaviour for proc shareability, providing a consistent experience for developers transitioning to Ractor‑safe code.
まとめ
try_make_shareable equips Rails applications with a unified way to attempt Ractor‑shareability for any object, while honouring the configurable unshareable_proc_action policy. This addition broadens Ractor support without disrupting existing applications.