Action Cableのアダプタでeager loadingをRedisとPostgreSQLのみに限定

rails/rails

Action Cableは、Redis と PostgreSQL のサブスクリプションアダプタだけを eager loading から除外し、他の軽量アダプタは従来どおり eager load されるように変更しました。これにより起動時のロードコストを抑えつつ、特定アダプタに依存するオプションの遅延ロードを維持します。

背景

Action Cableloader.do_not_eager_load にサブスクリプションアダプタのディレクトリ全体を指定し、オプション依存を持つアダプタを遅延ロードしていました。この方針は、Redis アダプタが BaseChannelPrefix をファイルロード時に参照するため、Zeitwerk のラジウム競合で NameError が発生する問題を引き起こしました(PR #57249 では明示的 require を追加して回避)。しかし、Redis と PostgreSQL 以外のアダプタはコードサイズが小さいため、eager loading をスキップしても得られるメリットが限定的でした。結果として、過度な除外が不要な複雑さをもたらすことが判明しました。

この背景から、ディレクトリ単位の除外から、影響の大きい Redis と PostgreSQL のファイルのみを対象に限定する方針が採用されました。

技術的な変更

actioncable/lib/action_cable.rbdo_not_eager_load の対象変更

loader.do_not_eager_load が受け取るパスをディレクトリから個別ファイルへ変更し、コメントで意図を明示しました。

@@ -41,7 +41,10 @@
   )

   loader.do_not_eager_load(
-    "#{lib}/action_cable/subscription_adapter", # Adapters are required and loaded on demand.
+    # These adapters trigger optional dependencies so they are required and loaded on demand.
+    "#{lib}/action_cable/subscription_adapter/redis.rb",
+    "#{lib}/action_cable/subscription_adapter/postgresql.rb",

     "#{lib}/action_cable/test_helper.rb",
     Dir["#{lib}/action_cable/**/test_case.rb"]
   )

この変更により、Redis と PostgreSQL の adapter だけが eager loading から除外され、他の async.rbinline.rbtest.rb などは標準的に eager load の対象となります。

actioncable/lib/action_cable/subscription_adapter/redis.rb の不要な require の削除

Redis アダプタから、BaseChannelPrefix の明示的 require が削除されました。ファイルは依然として Base を継承しますが、do_not_eager_load に列挙されているため、実行時に初めてロードされ、Zeitwerk が自動的に依存クラスを解決します。

@@ -7,9 +7,6 @@

 require "active_support/core_ext/hash/except"
-
-require "action_cable/subscription_adapter/base"
-require "action_cable/subscription_adapter/channel_prefix"
-
 module ActionCable
   module SubscriptionAdapter
     class Redis < Base # :nodoc:

この削除は、アダプタ自身が依存をロードするという既存のスタイルrequire がなくても Zeitwerk が適切に処理)に合わせたものです。

変更の影響

  • Redis と PostgreSQL 以外のアダプタは起動時に eager load され、ロード回数が減少し、NameError のレースコンディションリスクが低減します。
  • 既存の config.action_cable.subscription_adapter = :redis 等の設定は動作に影響しません。削除された require は不要なオーバーヘッドだけだったため、互換性は保たれます。

設計判断

スコープ限定の除外という選択は、起動時間の最適化コードベースの一貫性 のトレードオフを再評価した結果です。ディレクトリ全体を除外すると、軽量な adapter まで遅延ロードされ、不要な遅延が発生します。一方で Redis と PostgreSQL はオプション依存(外部サービスクライアント)を持つため、起動時に必ずしもロードすべきでないという設計方針が残ります。

また、redis.rb から require 行を削除した点は、「アダプタは自らの依存を明示的に require しない」という既存スタイルを尊重したものです。これにより、コード量が減り、コメントと実装の乖離がなくなります。

総合的に、必要最小限の除外対象に絞ることで、パフォーマンス向上と保守性向上の両立を図った設計判断と言えます。

まとめ

この PR は Action Cable のサブスクリプションアダプタに対し、Redis と PostgreSQL のみを eager loading から除外し、他の軽量アダプタは標準的に eager load させることで、起動時のロードコストを削減しつつ、既存の遅延ロード方針を維持しました。不要になった require の削除はコードベースの一貫性を保ち、今後のアダプタ追加時の指針にもなります。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
9a7560f7

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

リード文、背景、技術的変更、設計判断、まとめが明確に配置されており、総論→各論→結論の構成が保たれています。

カスタムMarkdown構文 ⚠ WARNING

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

コードブロックのファイル名付きハイライトは正しい形式ですが、PRリンクが "[PR #57582]" と記述されており、要求仕様の "[#123]" 形式と完全には一致しません。

対象読者への適合性 ✓ PASS

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

エンジニア向けの専門的な記述で、初心者向けの過度な説明はなく適切です。

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

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

各セクションが総論・各論・結論の段落に分かれ、トピックセンテンスで始まり、1段落1トピック・適切な長さが保たれています。

Diff内容との照合 ✓ PASS

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

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

技術用語の正確性 ✓ PASS

技術用語の正確な使用

eager loading、loader.do_not_eager_load、Redis、PostgreSQL などの用語は正しく使用され、PR内容と一致しています。

説明の技術的正確性 ✓ PASS

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

技術的な説明はDiffとPRの記述に基づき、論理的に正確です。

事実の突合 ✓ PASS

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

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

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

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

PR番号 #57582 などの数値は正しく記載されています。

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

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

記事タイトルはPRの主旨「Redis と Postgres のみ eager loading をスキップ」ことを正確に表現しています。

外部知識の正確性 ✓ PASS

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

LTS やリリース日程など、PRに記載されていない外部知識は含まれていません。

時間表現の正確性 ✓ PASS

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

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