Capistrano and Ferret DRB

June 19, 2008 - 2 minute read -
Automation capistrano ferret

This is a bit of a followup to my previous post on Capistrano with Git and Passenger. I decided to use Ferret via the acts_as_ferret (AAF) plugin. Ferret is a full-text search inspired by Apache's Lucene but written in Ruby.

Basically Ferret and Lucene keep a full-text index outside of the database that allows it to quickly perform full-text searches and find the identifers of rows in your database. Then you can go get those objects out of the database. It's pretty slick.

Ferret uses DRb as a means of supporting multiple-concurrent clients and for scaling across multiple machines. You really don't need to know much about DRb to use AAF, but you do need to run the ferret DRb server in your production environment. Which gets us to...

Automating The Starting and Stopping of ferret_server

A few lines of code in your Capistrano deploy.rb and you are off and running.

before "deploy:start" do
  run "#{current_path}/script/ferret_server -e production start"
end </p>
<p>after "deploy:stop" do
  run "#{current_path}/script/ferret_server -e production stop"
end</p>
<p>after 'deploy:restart' do
  run "cd #{current_path} && ./script/ferret_server -e production stop"
  run "cd #{current_path} && ./script/ferret_server -e production start"
end

Except it doesn't work. I ended up with some errors like: could not execute command no such file to load -- /usr/bin/../config/environment

It also ends up that it's not Capistrano's fault.

Acts As Ferret server_manager.rb

In the file vendor/plugins/acts_as_ferret/lib/server_manager.rb there is a line that sets up where to look for its environment information. For some reason this is the default:

  # require(File.join(File.dirname(__FILE__), '../../../../config/environment'))
  require(File.join(File.dirname(ENV['_']), '../config/environment'))

If you notice, there is a line commented out. It just so happens that uncommenting that line and commenting out the other fixed the issue for me. It ends up that ENV['_'] points to the base path of the executable and thats /usr/bin/env. And that doesn't work. I'm not sure why that's the default behavior.

Anyway, it's easily fixed:

  require(File.join(File.dirname(__FILE__), '../../../../config/environment'))
  # require(File.join(File.dirname(ENV['_']), '../config/environment'))

With that fix in place, the Capistrano deployment will restart the Ferret DRb server when you deploy your application.

Update According to John in the comments below you can fix the AAF problem without changing the code as well. Just add default_run_options[:shell] = false to your Capistrano script and that will take care of it.