AbstractController::Caching の view_cache_dependency を Ractor セーフに

rails/rails

AbstractController::Caching の view_cache_dependency が Ractor 共有可能な Proc に変換され、Ractor 環境でも安全に利用できるようになりました。これにより、Rails のキャッシュ依存関係宣言がマルチスレッド・マルチプロセスの新しい実行モデルと整合します。

背景

Ractor は Ruby の並行実行モデルで、オブジェクトを共有する際に明示的な共有可能性が求められます。AbstractController::Caching.view_cache_dependency はブロック(Proc)を受け取り、内部で _view_cache_dependencies 配列に保持し、後に instance_exec で実行しますが、従来はその Proc が共有可能かどうかのチェックが行われていませんでした。

その結果、Ractor が有効な環境でキャッシュ依存関係を宣言すると、未共有の Proc が Ractor 境界を越えて渡され、Ractor::IsolationError が発生するリスクがありました。既存の実装は class_attribute :_view_cache_dependencies, default: [] とし、配列を直接 += で拡張していましたが、配列自体もミュータブルであるため安全性が確保できませんでした。

この問題を放置すると、Ractor 移行を検討するアプリケーションでキャッシュ機構が利用できず、パフォーマンスやスケーラビリティの恩恵を受けられないという実務的な障壁が残ります。そこで、view_cache_dependency を Ractor セーフに改修する必要が生じました。

技術的な変更

_view_cache_dependenciesclass_attribute として定義され、デフォルト値を [].freeze に変更しました。さらに view_cache_dependency の実装を、既存の配列に対するミュータブルな追加から、フリーズされた新しい配列を生成して置き換える形に刷新し、追加される Proc には ActiveSupport::Ractors.try_shareable_proc を通すことで共有可能性を保証します。

変更前:

class_attribute :_view_cache_dependencies, default: []

module ClassMethods
  def view_cache_dependency(&dependency)
    self._view_cache_dependencies += [dependency]
  end
end

変更後:

class_attribute :_view_cache_dependencies, default: [].freeze

module ClassMethods
  def view_cache_dependency(&dependency)
    self._view_cache_dependencies = [
      *_view_cache_dependencies,
      ActiveSupport::Ractors.try_shareable_proc(dependency)
    ].freeze
  end
end

この改修により、_view_cache_dependencies が常に凍結された配列となり、変更時に新しい配列を生成して置き換えるため、参照の競合が起きません。また、try_shareable_proc が返す Proc は Ractor 境界で安全に共有できることが保証され、非共有 Proc が渡された場合は例外が発生して早期に問題を検出できます。既存の非 Ractor 環境では挙動に差異がなく、互換性が保たれます。

設計判断

class_attributefreeze を組み合わせた設計は、Rails の設定系オブジェクトで広く採用されている不変性パターンを踏襲しています。新たに別属性を導入せず、既存の _view_cache_dependencies を拡張した点は、API の破壊を避けつつ安全性を高める狙いです。

ActiveSupport::Ractors.try_shareable_proc の使用は、Ractor 共有可能性の判定ロジックを Rails コアに委任する選択です。これにより、Proc が共有不能である場合に即座に例外を投げ、テストで検証できるようになりました(ActiveSupport::Testing::RactorsAssertions を利用)。同様の安全化は、同時期にマージされた PR #57743 での InheritableOptions#to_h の修正と同様のパターンです。

結果として、最低限のコード変更で後方互換性と Ractor 安全性の両立が実現されました。配列の凍結と Proc の変換という二重の防御が、将来的な拡張や他コンポーネントからの呼び出しに対しても堅牢な基盤を提供します。

まとめ

今回の変更は、AbstractController::Caching.view_cache_dependency を Ractor 共有可能な形に変換し、内部配列を凍結することでマルチプロセス実行時の安全性を確保した点が核心です。これにより、Rails アプリケーションはキャッシュ依存関係を宣言したまま Ractor 環境へ移行でき、追加の回避策を講じる必要がなくなります。

テストスイートには ActiveSupport::Testing::RactorsAssertions を用いた検証が追加され、_view_cache_dependencies が Ractor 共有可能であることを自動的に確認しています。変更は既存コードへの影響を最小限に抑えつつ、Rails が提供する新しい並行実行モデルへの対応を前倒しで実装した好例と言えるでしょう。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
3e9ed865

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

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

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

カスタムMarkdown構文 ✓ PASS

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

コードブロックは `ruby:actionpack/lib/abstract_controller/caching.rb` の形式で正しく記述され、PRリンクは `[PR #57754](URL)` の形で正しくハイパーリンク化されています。

対象読者への適合性 ✓ PASS

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

Railsコア開発者向けの高度な技術内容で、初心者向けの余計な説明はありません。

パラグラフ・ライティング ⚠ WARNING

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

ほとんどの段落はトピックセンテンスで始まり、1段落1トピックになっていますが、背景セクションの段落が6文程度でやや長く、分割すると可読性が向上します。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは提供されたDiffと完全に一致し、変更点(freeze、try_shareable_proc の使用)が正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

Ractor、Proc、class_attribute、freeze などの用語が正しく使用されています。

説明の技術的正確性 ✓ PASS

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

技術的な説明はDiffとPR Descriptionに基づいており、誤りや根拠のない主張はありません。

事実の突合 ✓ PASS

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

すべての主張がPRタイトル、Description、Diffで裏付けられており、ハルシネーションは検出されません。

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

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

PR番号やファイルパス、コードの行数等に誤りはありません。

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

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

記事タイトルはPRの目的「Make AbstractController::Caching.view_cache_dependency ractor safe」を日本語で的確に表現しています。

外部知識の正確性 ✓ PASS

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

外部のバージョンサポート情報やベンチマーク等、PRに記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現の歪曲はなく、PRの記述と一致しています。