Redis アダプタで `id: nil` を尊重するよう修正
ActionCable の Redis アダプタは、接続 ID を自動付与するロジックで id: nil を指定できないバグがありました。本修正により、明示的に id: nil を設定した場合でも CLIENT SETNAME が実行されず、利用者の意図が正しく反映されます。
背景
ActionCable::SubscriptionAdapter::Redis.redis_connector は接続設定ハッシュに対して config[:id] ||= "ActionCable-PID-#{$$}" と記述しており、||= が nil を未設定とみなしてデフォルト名で上書きしていました。ドキュメントでは id: nil を指定すると名前付けをプロキシに委任できると説明されているにも関わらず、実装がそれを無視していました。さらに SubscriptionAdapter::Base#identifier は unless key?(:id) ガードで nil を保持していたため、二つのロジックが矛盾していました。
技術的な変更
redis_connector の実装を config[:id] = "ActionCable-PID-#{$$}" unless config.key?(:id) に置き換え、キーが存在しない場合のみデフォルトを設定するようにしました。これにより id: nil が明示的に渡されたときは上書きされず、client.id が nil のまま保持されます。
cattr_accessor :redis_connector, default: ->(config) do
config = config.except(:adapter, :channel_prefix)
- config[:id] ||= "ActionCable-PID-#{$$}"
+ config[:id] = "ActionCable-PID-#{$$}" unless config.key?(:id)
redis_config = if config.key?(:sentinels)
::RedisClient.sentinel(**config)
テスト側も RedisAdapterTest::ConnectorCustomIDNil が client.id を直接検証するよう修正し、id: nil が正しく尊重されることを確認できるようになりました。
test "sets connection id for connection" do
client = @adapter.send(:redis_connection)
if connection_id.nil?
- assert_nil connection_id
+ assert_nil client.id
else
assert_equal connection_id, client.id
end
end
設計判断
この変更は 既存の config[:id] キーを拡張するだけ のシンプルなアプローチで、Base アダプタとロジックを統一しました。新たな設定キーやオプションを導入せず、後方互換性を保ちつつ期待通りの振る舞いを実現しています。ガード条件の統一はコードベース全体の一貫性を高め、将来的なメンテナンス負荷を低減します。
まとめ
id: nil が正しく保持されるようになったことで、プロキシ環境や外部命名管理下で ActionCable の Redis 接続を柔軟に構成できます。最小限の差分で既存動作を壊さずバグを修正した点が本変更の価値です。