RedisCacheStore が redis-client に再実装され、DeprecatedRedisCacheStore が追加

rails/rails

RedisCacheStore の実装が redis-client に置き換えられ、旧実装は DeprecatedRedisCacheStore として分離されました。これにより依存が軽量化されつつ、既存の :redis オプションは段階的に廃止されます。

背景

Rails のキャッシュ機構で使用されてきた ActiveSupport::Cache::RedisCacheStore は、長年 redis gem と Redis::Distributed に依存していました。Redis::Distributed が実装上のブロッカーとなり、モダンな RESP3 への移行や依存サイズの削減が難しかったのです。そこで、軽量で RESP2/3 をサポートする redis-client への全面的な置き換えが計画されました。結果として、キャッシュの挙動を変えずに依存関係の刷新が実現されました。

技術的な変更

Gemfileredis-client >= 0.28.0 が追加され、Gemfile.lock でもバージョンが更新されています。依存が redis (>= 4.0.1) から redis-client (>= 0.28.0) に変わり、インストールサイズが大幅に削減されました。

@@ -70,6 +70,7 @@ end

 # Active Support
 gem "dalli"
+gem "redis-client", ">= 0.28.0"
 gem "listen", "~> 3.3", require: false

ActiveSupport::Cache モジュールに DeprecatedRedisCacheStore が autoload され、旧実装への参照が明示的に分離されました。これにより :redis オプションが渡された際に自動的に旧ストアへフォールバックする仕組みが実装されています。

module Cache
  autoload :MemCacheStore,    "active_support/cache/mem_cache_store"
  autoload :NullStore,        "active_support/cache/null_store"
  autoload :RedisCacheStore,  "active_support/cache/redis_cache_store"
+  autoload :DeprecatedRedisCacheStore,  "active_support/cache/deprecated_redis_cache_store"

  # These options mean something to all cache implementations. Individual cache
  # implementations may support additional options.
end

redis_cache_store.rb の実装が大幅に書き換えられ、redis-client が直接使用されるようになりました。gem "redis" の宣言は削除され、代わりに gem "redis-client" を要求し、require "redis-client" を読み込みます。また RedisClient.ring が導入され、複数ノード構成の扱いが簡潔に実装されています。

redis_client_min_version = "0.28.0"
begin
  gem "redis-client", ">= #{redis_client_min_version}"
rescue LoadError
  raise LoadError, <<~MSG
    The Redis cache store requires the redis-client gem version #{redis_client_min_version} or later.
    Please add it to your Gemfile:
      gem "redis-client", ">= #{redis_client_min_version}"
  MSG
end

require "redis-client"

RedisCacheStorenew メソッドは :redis オプションが渡された場合に DeprecatedRedisCacheStore へ委譲し、同時にデプリケーション警告を出します。これにより既存アプリは動作を維持しつつ、将来的に :url または :client オプションへの移行が促されます。

def self.new(**options)
  if options[:redis]
    ActiveSupport.deprecator.warn(<<~MSG.squish)
      Passing a Redis or ConnectionPool instance via the `:redis` configuration to ActiveSupport::Cache::RedisCacheStore
      is deprecated and will be removed in Rails 8.3.
    MSG
    return DeprecatedRedisCacheStore.new(**options)
  end
  # ...新しい実装続く...
end

機能面では GETDEL コマンドへの対応が追加され、delete: true オプションで読み取りと同時削除が可能になりました。また read_multi / write_multiredis-clientmget / mset にマッピングされ、バッチ処理のオーバーヘッドが低減されます。

# read_serialized_entry (抜粋)
if options[:delete]
  value = client.call("GETDEL", namespaced_key)
else
  value = client.call("GET", namespaced_key)
end

テストスイートも更新され、RedisClient を用いた接続チェックや新ストアの挙動検証が追加されています。旧ストア向けのテストは DeprecatedRedisCacheStoreTests として分離され、両方の互換性が CI で保証されます。

redis_up = begin
  RedisClient.new(url: REDIS_URL, protocol: 2).call("ping")
  true
rescue RedisClient::ConnectionError
  false
end

設計判断

Rails は互換性を保ちつつ依存を軽量化するため、既存の :redis オプションを段階的に廃止し、代替として DeprecatedRedisCacheStore を導入しました。redis-clientring 機能を活用することで分散構成をシンプルに扱えるようになり、追加の gem (redis) を削除できました。さらに、設定インターフェースは :url または :client に統一され、将来の機能追加やプロトコル拡張が容易になる設計です。デプリケーション警告により利用者は安全に移行でき、既存コードは即座に破壊されません。

まとめ

本 PR により RedisCacheStoreredis-client に完全移行し、依存が軽量化されました。旧実装は DeprecatedRedisCacheStore として残り、:redis オプションは非推奨として段階的に削除されます。開発者は :url:client を用いて新しいストアを利用でき、機能面でも GETDEL などの最新コマンドがサポートされます。

記事メタデータ

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

この記事は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 #57004](URL)` となっており、要求された `[#57004](URL)` 形式になっていません。

対象読者への適合性 ✓ PASS

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

対象は Rails のコア開発者・エンジニアであり、専門的な用語と実装詳細が中心です。初心者向けの過度な説明はありません。

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

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

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

Diff内容との照合 ✓ PASS

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

記事中のコードブロックは提供された Diff と一致しており、ファイル名・変更内容ともに正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

用語(RedisCacheStore、redis-client、DeprecatedRedisCacheStore、RESP2/3 など)は PR 内容と合致し、誤用はありません。

説明の技術的正確性 ✓ PASS

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

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

事実の突合 ✓ PASS

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

すべての事実・主張は PR タイトル、Description、Diff から確認でき、捏造や推測はありません。

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

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

PR 番号 #57004、バージョン 0.28.0 など数値は正確です。

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

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

記事タイトルは PR の内容(RedisCacheStore を redis-client で再実装)を正確に表現しています。

外部知識の正確性 ✓ PASS

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

RESP2/3 への言及は PR の記述に基づくもので、外部知識の付加はありません。

時間表現の正確性 ✓ PASS

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

Rails 8.3 での削除という時間表現はコード中のデプリケーション警告と一致しています。