Restarting Rails Redis Cache Store connection upon Passenger fork
caching, passenger, redis, ruby-on-rails
Solution
Take a look on reconnect method of redis store: https://github.com/jodosha/redis-store/blob/master/redis-activesupport/lib/active_support/cache/redis_store.rb
So basically your fork block should look like:
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
if forked
Rails.cache.reconnect
end
end
end
Problem
I want to use redis cache store (using redis-store gem). It works fine locally but when going on production where Passenger forks multiple instances of Rails workers we're getting Redis errors which indicate synchronization problems between the different instances regarding Redis access. An example for such an error is ``` Got '7' as initial reply byte. If you're running in a multi-threaded environment, make sure you pass the :thread_safe option when initializing the connection. If you're in a forking environment, such as Unicorn, you need to connect to Redis after forking. redis (2.2.2) lib/redis/connection/ruby.rb:78:in `format_reply' ``` I have done some reading and learned that each Passenger worker instance must create its own Redis connection. This might be implemented using the following code ``` #config/initializers/redis_fork_init.rb if defined?(PhusionPassenger) PhusionPassenger.on_event(:starting_worker_process) do |forked| if forked $redis = Redis.new end end end ``` Assuming Redis access is done through $redis all over the code - this solution is great. My question is - how can I create a new Redis connection that will be used when I do `Rails.cache` operations such as read, write etc... ? my config/environments/production.rb includes the following: ``` config.cache_store = :redis_store, { :host => 'localhost', :port => 6379, :thread_safe => true } ``` Using Rails 3.2.3, Redis 2.2.2, redis-store 1.1.1, Passenger 3.0