LogSubscriber の log_levels を Ractor セーフにする変更

rails/rails

LogSubscriber のクラス属性 log_levels を凍結し、更新時にも凍結したハッシュを保持することで、Ractor 間で安全に共有できるようにしました。

背景

これまで LogSubscriber.log_levels は可変ハッシュとして定義されており、Ractor で共有する際に不変性が保証されていませんでした。Ractor はオブジェクトの共有に厳格な制約を設けており、共有可能(shareable)であることが要求されます。そのため、subscribe_log_level がハッシュをマージした結果をそのまま保持すると、Ractor 間で渡したときに例外が発生するリスクがあります。PR #57919 はこのリスクを排除し、log_levelsRactor 安全にすることを目的としています。

技術的な変更

log_levels の初期化を凍結するため、class_attribute :log_levels のデフォルト値を {} から {}.freeze に変更しました。また、subscribe_log_level でハッシュをマージした後に .freeze を付与し、更新後も不変オブジェクトとなるようにしました。

@@
-    class_attribute :log_levels, instance_accessor: false, default: {} # :nodoc:
+    class_attribute :log_levels, instance_accessor: false, default: {}.freeze # :nodoc:
@@
-          self.log_levels = log_levels.merge(method => LEVEL_CHECKS.fetch(level))
+          self.log_levels = log_levels.merge(method => LEVEL_CHECKS.fetch(level)).freeze

この変更により、log_levels は常に凍結されたハッシュで保持され、Ractor が要求する shareable な状態が保証されます。LEVEL_CHECKS は既に freeze されているため、追加のロジックは不要です。

テストコードも Ractor 共有可能性のアサーション を追加し、MyLogSubscriber.log_levels が shareable であることを検証しています。

@@
+require "active_support/testing/ractors_assertions"
@@
   include ActiveSupport::LogSubscriber::TestHelper
+  include ActiveSupport::Testing::RactorsAssertions
@@
   def test_log_levels_are_ractor_safe
     assert_ractor_shareable MyLogSubscriber.log_levels
   end

設計判断

クラス属性の不変化を保証するという方針が採られました。既存の API(LogSubscriber.subscribe_log_level の呼び出し方)やデフォルト動作は変更せず、内部でハッシュを凍結するだけの最小限の侵入で実装されています。log_levels を別の属性名やラッパーメソッドでラップする案は検討されなかったようです。これにより、既存コードへの影響がなく、Ractor 対応という新たな要件だけを満たす設計となっています。

まとめ

LogSubscriber.log_levels{}.freeze で初期化し、マージ後も .freeze して保持することで、Ractor 間で安全に共有できる不変ハッシュにしました。追加されたテストにより、その shareable 性が検証されています。この変更は振る舞いを変えずに Ractor 対応を実現し、今後の並行処理実装における安全性を高めます。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
2f3691c4

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

リード文、背景、技術的変更、設計判断、まとめの5セクションが揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライトとPRリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

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

Rails エンジニア向けの適切な技術レベルで記述されており、不要な初心者向け解説はありません。

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

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

各セクションは総論・各論・結論のパラグラフ構成で、トピックセンテンスが冒頭にあり、段落は1トピック・適切な長さで空行で区切られています。

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは提供されたDiffと完全に一致し、変更箇所・追加箇所が正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

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

説明の技術的正確性 ✓ PASS

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

技術的説明は Diff と PR の内容に基づき正確で、因果関係も適切に示されています。

事実の突合 ✓ PASS

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

全ての主張は PR の目的・実装内容に裏付けられており、捏造や推測はありません。

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

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

PR 番号 #57919 だけが言及されており、正確です。他の数値・固有名詞はありません。

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

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

記事タイトルは PR タイトルの意味を日本語で適切に表現しています。

外部知識の正確性 ✓ PASS

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

バージョンサポートやリリース日程など、PR に無い外部情報は含まれていません。

時間表現の正確性 ✓ PASS

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

時間表現は使用されておらず、PR の記述と矛盾はありません。