Run acts_as_solr in JRuby in background mode

Posted by Bhushan G Ahire | Posted in JRuby, Rails, ruby | Posted on 12-07-2010

0

When you try and run rake solr:start or rake solr:stop it uses Kernel.fork to spawn of a child process. However in JRuby this is disabled by default due to concurrency issues. And this prevents your solr rake tasks from running under a JRuby environment…

The Problem

When you try and run rake solr:start or rake solr:stop it uses Kernel.fork to spawn of a child process.
However in JRuby this is disabled by default due to concurrency issues. There is an option to enabling fork (jruby -J-Djruby.fork.enabled=true)
within JRuby but it is experimental and as the warning says, “WARNING: fork is highly unlikely to be safe or stable on the JVM.” as it can cause all sorts of weird and wonderful side-effects.

The Solution

The solution therefore is to simply alter the solr:start and solr:stop tasks to use Kernel.exec instead.
To do this find the solr rake tasks usually in {RAILS_ROOT}/vendor/acts_as_solr/lib/tasks/solr.rake. In the start task all that is required is to comment out the start of the fork block. so you only have the exec method call,
This will not start the solr process in the background. To do so you just have to add “&” at the end of the exec command, which causes the jar file to run in background mode.

task :start do
      require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
      begin
        n = Net::HTTP.new('127.0.0.1', SOLR_PORT)
        n.request_head('/').value

      rescue Net::HTTPServerException #responding
        puts "Port #{SOLR_PORT} in use" and return

      rescue Errno::ECONNREFUSED #not responding
        Dir.chdir(SOLR_PATH) do
            exec "java #{SOLR_JVM_OPTIONS}
-Dsolr.data.dir=#{SOLR_DATA_PATH} -Djetty.logs=#{SOLR_LOGS_PATH}
-Djetty.port=#{SOLR_PORT} -jar start.jar &"
          sleep(5)
          File.open("#{SOLR_PIDS_PATH}/#{ENV['RAILS_ENV']}_pid", "w"){ |f| f << pid}
          puts "#{ENV['RAILS_ENV']} Solr started successfully on #{SOLR_PORT}, pid: #{pid}."
        end
      end
    end

and in the end task just comment out the begining of the fork block so you are left with

  task :stop do
    require "#{File.dirname(__FILE__)}/../../config/solr_environment.rb"
      file_path = "#{SOLR_PIDS_PATH}/#{ENV['RAILS_ENV']}_pid"
      if File.exists?(file_path)
        File.open(file_path, "r") do |f|
          pid = f.readline
          Process.kill('TERM', pid.to_i)
        end
        File.unlink(file_path)
        Rake::Task["solr:destroy_index"].invoke if ENV['RAILS_ENV'] == 'test'
        puts "Solr shutdown successfully."
      else
        puts "PID file not found at #{file_path}. Either Solr is not running or no PID file was written."
      end
  end

you should now be able to run your solr rake tasks under jruby with out any problems..

Write a comment

You must be logged in to post a comment.