ラムダ定数を Ractor 共有可能にするラップ追加

rails/rails

Action Pack の定数に格納されたラムダを ActiveSupport::Ractors.shareable_lambda でラップし、Ractor 環境でも安全に共有できるようにしました。機能的な変更はなく、既存の振る舞いをそのまま保ちつつマルチスレッド安全性を確保します。

背景

Ractor が導入された Ruby では、オブジェクトはコピー可能または共有可能である必要があります。Action Pack 内ではミドルウェアの判定やパラメータ解析、URL 生成などで多数のラムダが定数として保持されており、これらはデフォルトでは Ractor 間で共有できません。

定数に格納されたラムダは多数のコードパスで直接呼び出されるため、個別にリファクタリングするコストが高く、既存 API の互換性を保つことが重要です。そのため、振る舞いを変えずに共有可能にする手段が求められました。

この課題に対処するため、ActiveSupport::Ractors.shareable_lambda を用いたラップ方式が採用されました。

技術的な変更

対象となる定数ラムダはすべて ActiveSupport::Ractors.shareable_lambda でラップされ、Ruby 4.0 以降で共有可能な Proc が生成されます。Ruby 3 系では従来と同等の動作を維持します。

-      INCLUDE = ->(list, action) { list.include? action }
-      EXCLUDE = ->(list, action) { !list.include? action }
-      NULL    = ->(list, action) { true }
+      INCLUDE = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { list.include? action })
+      EXCLUDE = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { !list.include? action })
+      NULL    = ActiveSupport::Ractors.shareable_lambda(&->(list, action) { true })
-        Mime[:json].symbol => -> (raw_post) {
+        Mime[:json].symbol => ActiveSupport::Ractors.shareable_lambda(&-> (raw_post) {
           data = ActiveSupport::JSON.decode(raw_post)
           data.is_a?(Hash) ? data : { _json: data }
-        }
+        })
-      ESCAPE_PATH    = ->(value) { Router::Utils.escape_path(value) }
-      ESCAPE_SEGMENT = ->(value) { Router::Utils.escape_segment(value) }
+      ESCAPE_PATH    = ActiveSupport::Ractors.shareable_lambda(&->(value) { Router::Utils.escape_path(value) })
+      ESCAPE_SEGMENT = ActiveSupport::Ractors.shareable_lambda(&->(value) { Router::Utils.escape_segment(value) })
-        SERVE = ->(app, req) { app.serve req }
-        CALL  = ->(app, req) { app.call req.env }
+        SERVE = ActiveSupport::Ractors.shareable_lambda(&->(app, req) { app.serve req })
+        CALL  = ActiveSupport::Ractors.shareable_lambda(&->(app, req) { app.call req.env })
-      PATH    = ->(options) { ActionDispatch::Http::URL.path_for(options) }
-      UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
+      PATH    = ActiveSupport::Ractors.shareable_lambda(&->(options) { ActionDispatch::Http::URL.path_for(options) })
+      UNKNOWN = ActiveSupport::Ractors.shareable_lambda(&->(options) { ActionDispatch::Http::URL.url_for(options) })

これらの変更はラップのみで実装され、ラムダ本体のロジックは一切変更されていません。そのため、既存のテストはすべてパスし、リクエスト処理や URL ヘルパーの振る舞いに差分は生じません。

設計判断

ラップのみで共有可能にする という方針は、既存 API の互換性を最小限の侵入で保つことが目的です。代替案としては個別にコードをリファクタリングし外部クラスへ移す方法が考えられましたが、全定数ラムダに対して一括適用できるユーティリティを使う方が保守コストを低減します。

ActiveSupport::Ractors.shareable_lambda は Ruby 4.0 以降で共有可能な Proc を生成し、旧バージョンでは従来通りの Proc を返すため、バックワード互換性が確保されます。これにより、Ractor 未使用のアプリケーションや古い Ruby バージョンでの動作に影響を与えません。

この設計は「最小限の変更で新しい並行実行モデルをサポートする」Rails の設計哲学と一致しています。

まとめ

本 PR は Action Pack 内の定数ラムダを ActiveSupport::Ractors.shareable_lambda でラップし、Ractor 環境でも安全に共有できるようにしました。機能的な変更はなく、既存コードの互換性を保ちつつマルチスレッド安全性を向上させた点が最大の意義です。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
0efe7a0b

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
3回 (改善を経て承認)
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断(任意)、まとめの全てが揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは `ruby:ファイルパス` 形式で正しく記述され、PRリンクは `[#57681](URL)` の形式で正しくリンク化されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

対象は Rails エンジニアであり、専門用語や実装詳細が中心で初心者向けの余計な説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論・各論・結論の段落構成になっており、トピックセンテンスが先頭にあり、1段落1トピック、段落長も適切です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中のコード変更は提供された Diff と完全に一致しており、追加・削除行ともに正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

Ractor、shareable_lambda、Proc などの用語は PR と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

機能的変更がないこと、テストが通ること、バックワード互換性の確保などの説明は PR 内容と合致しています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

すべての主張は PR のタイトル・説明・Diff で裏付けられており、根拠のない推測や数値的主張はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #57681 以外の数値や固有名詞の誤りは見当たりません。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR タイトル「Make some lambdas in constants shareable」の意味を日本語で正確に表現しています。

外部知識の正確性 ⚠ WARNING

PRに記載のない外部知識(LTS、サポート状況など)の不使用

「Ruby 3 系では従来と同等の動作を維持します」という記述は PR に明示されておらず、外部知識に基づく推測とみなされます。技術的に妥当ではありますが、出典がない点が指摘されます。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の記述はなく、PR と食い違う表現もありません。