Using acts as ferret with phusion passenger / mod_rails

The passenger manual makes it clear that you need to close and reestablish your connections to things like memcached after it forks to avoid inadventently sharing file handles. The reason is well and clearly explained there.The api to do this is simple – just place this kind of code in your environment.rb file:

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      # We’re in smart spawning mode.
      reestablish connections
    else
      # We’re in conservative spawning mode. We don’t need to do anything.
    end
  end
end

All well and good, but how exactly do you reestablish those connections?In our case we have to deal with memcached and ferret (with ferret running in a DRb server via the acts_as_ferret plugin).Memcached is dead easy:

CACHE.reset

Ferret not so easy. It turns out that DRb has no in-built way to close its pool of connections. So a monkey patch is the only thing to do. I was inspired by some code you can find here. But since we want to blindly close all the connections, our case is simpler:

  class DRb::DRbConn
    def self.close_all
      @mutex.synchronize do
        @pool.each {|c| c.close}
        @pool = []
      end
    end
  end

  DRb::DRbConn.close_all

DRb will happily reconnect by itself when needed after its connection pool has been emptied.Putting it all together, it looks like this:

if defined?(PhusionPassenger)
  # monkey patch drb so we can close its connections
  class DRb::DRbConn
    def self.close_all
      @mutex.synchronize do
        @pool.each {|c| c.close}
        @pool = []
      end
    end
  end

  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      # We’re in smart spawning mode.
      CACHE.reset  # memcached
      DRb::DRbConn.close_all  # ferret
    else
      # We’re in conservative spawning mode. We don’t need to do anything.
    end
  end
end

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s