エンジニアの桂です。
ヒカカク!では Action Cable を運用しているのですが、 Rails 6 へのアップデートの際に例外が発生する事案がありました。その原因と回避策について紹介します。
現象
GCP の Cloud Memorystore を Action Cable の Redis サーバーに設定した状態で ActionCable.server.broadcast
すると以下のような例外が発生した。
Redis::CommandErrorERR unknown command 'client'
発生箇所はこちら。
原因
Action Cable が Redis.new
するとき、自動的に id
を設定する。Redis::Client
は id
が設定されると Redis サーバーに client
命令を発行してその id
を設定するが、 Cloud Memorystore は client
命令に対応していない。
回避策
エラー発生箇所のコードから、 Redis.new
の際、 id
に nil
渡してやると client
命令を発行せずに済むことが分かります。
Action Cable 曰く、
ということなので、ちょっと目的は違いますが、この値をパッチしてやります。
# config/initializers/action_cable.rbrequire 'action_cable/subscription_adapter/redis'ActionCable::SubscriptionAdapter::Redis.redis_connector = ->(config) do
config[:id] = "ActionCable-PID-#{$$}" unless config.has_key?(:id)
::Redis.new(config.except(:adapter, :channel_prefix))
end
これで config/cable.yml
から id: null
を渡してやることができるようになり、 client
命令を回避することができました。
# config/cable.ymlproduction:
adapter: redis
url: <%= "redis://#{ENV['REDIS_HOST']}:6379/0" %>
id: null
コントリビューションはじめました
id
を明示的に null
に指定しても強制的に上書きされるのは一先ずよくない挙動だということで、 Rails に PR を出しておきました。