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..
