Mar 3, 2010

Capistrano & Sunspot in Rails

I've been messing around with Sunspot in Rails lately. One of the issues that I ran into is that the index is stored in the application root's solr directory. That's usually not a big deal, but if you use capistrano, then you know that you end up with a new application directory with each deploy. So how do you handle that?


Well, the proper way is to not rely on the built-in instance of Solr that comes with Sunspot. Instead, you're supposed to treat Solr like MySQL; A component that's independent of your application. As somebody who does not program Java, I found the instructions on doing this strange enough that I decided not to use this route. (And don't bother installing Solr via Ubuntu's packages.. what a nightmare that turns out to be..)

Instead, I created a solr directory in my capistrano shared directory. From there, I create a new symlink via capistrano and restart solr. In case you want to try this method (which again, is not the recommended path, but works in a pinch). Here are the relevant parts of my capistrano recipe.

First, before doing anything, I stop Solr/Sunspot:

task :before_update_code do
#stop solr:
run "cd #{current_path} && rake sunspot:solr:stop RAILS_ENV=#{rails_env}"
end


Next, I create the hook to run my solr tasks after the crontab and symlinks have been set:

after "deploy:update_crontab", "deploy:solr:symlink"


Lastly, I create the symlinks and restart Solr:

namespace :solr do
desc <<-DESC
Symlink in-progress deployment to a shared Solr index.
DESC
task :symlink, :except => { :no_release => true } do
run "ln -nfs #{shared_path}/solr #{current_path}/solr"
run "ls -al #{current_path}/solr/pids/"
run "cd #{current_path} && rake sunspot:solr:start RAILS_ENV=#{rails_env}"
end
end


Anyway, your mileage may vary. It's been fun playing with Sunspot and Solr. They have a great community and nice documentation too.

3 comments:

  1. Awesome post, just what I needed! Thanks!

    One question -- in the line:
    run "ls -al #{current_path}/solr/pids/"

    -- it seems that my system puts the solr pids in "../tmp/pids", is that a typo or am I missing something.

    Also, is there a reason you didn't use the "before" callback to stop solr? As in:

    before "deploy:update_code" do
    run "cd #{current_path} && rake sunspot:solr:stop RAILS_ENV=#{rails_env}"
    end

    ReplyDelete
  2. I don't think your solution work. Sunspot see the solr folder and won't generate the default configuration files, thus the solr server will failed to index anything. There will be a need to prepare configuration files.

    ReplyDelete
  3. the default configuration file should be source controlled under the solr/conf/ folder. Only solr/data/ and solr/pids/ are symlinked.

    ReplyDelete