Action Cable Redis アダプタを redis-client で再実装

rails/rails

Action Cable の Redis アダプタが従来の redis gem から軽量な redis-client に置き換えられ、依存サイズの削減と API の単純化が実現されました。これにより、機能的な振る舞いは維持しつつ、ランタイムのフットプリントが小さくなります。

背景

従来の Action Cable Redis アダプタは redis gem (>= 4, < 6) に強く依存しており、gem 自体が数百キロバイトに及ぶ大きさでした。PR #57004 でキャッシュストアが redis-client に置き換えられたことを受け、同様の軽量化を Action Cable にも適用する狙いがありました。redis-client は RESP2 プロトコルをデフォルトで使用し、サーバ側の要件変更は不要です。これにより、Rails アプリケーション全体の依存関係がシンプルになることが期待されました。

技術的な変更

依存ライブラリの差し替え として、actioncable/lib/action_cable/subscription_adapter/redis.rb の冒頭で gem "redis"gem "redis-client" に、require "redis"require "redis-client" に変更しました。

-gem "redis", ">= 4", "< 6"
-require "redis"
+gem "redis-client"
+require "redis-client"

接続生成ロジックの刷新 では、redis_connectorRedisClient.config または RedisClient.sentinel を呼び出し、返されたオブジェクトからプールを生成するようになりました。config から :adapter:channel_prefix を除外し、id が未指定ならデフォルトで ActionCable-PID-#{$$} を設定します。

-        ::Redis.new(config.except(:adapter, :channel_prefix))
+        config = config.except(:adapter, :channel_prefix)
+        config[:id] ||= "ActionCable-PID-#{$$}"
+
+        redis_config = if config.key?(:sentinels)
+          ::RedisClient.sentinel(**config)
+        else
+          ::RedisClient.config(**config)
+        end
+        redis_config.new_pool

ブロードキャストの実装変更 では、従来の publish メソッド呼び出しを call("publish", ...) に置き換え、redis-client の汎用呼び出しインターフェースに合わせました。

-        redis_connection_for_broadcasts.publish(channel, payload)
+        redis_connection_for_broadcasts.call("publish", channel, payload)

サブスクライブ側の処理 では、listen メソッドが conn.pubsub から取得した pubsub_client を使用し、subscribe ループや再接続ロジックを redis-client の API に合わせてリファクタリングされています。変更前後の大きなロジックは削除され、シンプルな pubsub_client.subscribe 呼び出しに集約されました。

テストコードの更新 も同様に RedisClient.config を用いたインスタンス生成に合わせ、call 系メソッドへ置き換えられました。これにより、テストは実装変更を正確に反映しています。

-      @redis_conn ||= ::Redis.new(cable_config.except(:adapter))
+      @redis_conn ||= ::RedisClient.config(**cable_config.except(:adapter)).new_client
@@
-      redis_conn.client("kill", "type", "pubsub")
+      redis_conn.call("client", "kill", "type", "pubsub")
@@
-        break if redis_conn.pubsub("numsub", channel).last > 0
+        break if redis_conn.call("pubsub", "numsub", channel).last > 0

設計判断

既存の設定キーを残す方針 が採用され、redis: という構成オプションは引き続きサポートされています。redis-client に切り替えることで API が変化しましたが、外部からの呼び出しシグネチャは可能な限り同一に保たれ、後方互換性が確保されています。

依存削減とシンプル化 を最優先にした設計選択は、redis-client が提供する軽量なコネクションプーリングとシンプルなコマンド呼び出しインターフェースに基づいています。結果として、Action Cable の Redis アダプタは機能的に等価でありながら、バンドルサイズが小さくなり、アプリケーション全体の依存ツリーが簡潔になります。

まとめ

本 PR は Action Cable の Redis アダプタを redis-client に置き換えることで、redis gem への大きな依存を排除し、API をシンプル化しました。変更は内部実装に留まり、既存の動作や設定オプションは維持されるため、利用者はコードや設定を変更せずに利益を享受できます。

記事メタデータ

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

この記事は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:ファイルパス```` 形式で正しく記述され、PRリンクは [#57533](URL) の形で適切にリンク化されています。

対象読者への適合性 ✓ PASS

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

内容は Action Cable の内部実装に詳しいエンジニア向けで、初心者向けの過剰な説明はありません。

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

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

各段落はトピックセンテンスで始まり、1段落1トピックで構成され、6文以内に収まっています。空行で段落が区切られており可読性が高いです。

Diff内容との照合 ✓ PASS

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

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

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「redis-client」「gem」「adapter」などの用語は PR 内容と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

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

技術的な主張は Diff と PR の記述に裏付けられており、因果関係も論理的です。

事実の突合 ✓ PASS

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

記事のすべての事実は PR タイトル・説明・Diff に基づいており、推測や根拠のない数値は記載されていません。

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

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

PR 番号 #57533 と #57004、ファイルパス、コード行の差分などの数値は正確です。

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

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

記事タイトルは PR タイトル「Reimplement Action Cable redis adapter with redis-client」を正確に日本語化しています。

外部知識の正確性 ✓ PASS

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

LTS やリリース日程といった外部知識は一切含まれておらず、PR に限定した情報のみが記載されています。

時間表現の正確性 ✓ PASS

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

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