Search code examples
ruby-on-railsredissidekiq

Redis with rails. You need to reconnect to Redis after forking error


I am using Redis with my Rails app. I have sidekiq gem installed too. My redis server runs in the same machine in default port.

I created a initializer which initalizes a redis lient.

config/initializers/redis.rb

$redis = Redis.new(:host => 'localhost', :port => 6379)

I have another initalizer that sets the number of accounts currently active in the system.

config/initializers/z_account_list.rb

$redis.set('accounts',Account.count);

In one of my views i am using this piece of code.

<div class="more-text">and <%= "#{$redis.get('accounts')}" %> more...</div>

When i set the value for accounts manually in redis without using the initializer, everything works fine. But when i add the initializer, i get

ActionView::Template::Error (Tried to use a connection from a child process without reconnecting. You need to reconnect to Redis after forking.):

I searched for the error. But most solutions are for resque and has something to do with after_fork. Since i am new to Rails and Redis and since i am not using Resque i am getting a little confused. Please help me out on this.


Solution

  • In forked environments like pushion passenger, we have to reconnect to redis whenever a worker is forked. My biggest confusion was where to put the reconnection statements. In many blogs it was suggested to put it in config/environments.rb. But it didn't work for me.

    I added

    if defined?(PhusionPassenger)
      PhusionPassenger.on_event(:starting_worker_process) do |forked|
        if forked
          $redis.client.disconnect
          $redis = Redis.new(:host => 'localhost', :port => 6379)
          Rails.logger.info "Reconnecting to redis"
        else
          # We're in conservative spawning mode. We don't need to do anything.
        end
      end
    end
    

    to config/initializers/redis.rb and everything started working fine.