Class: ActsAsFerret::Server::Server
- Inherits:
-
Object
- Object
- ActsAsFerret::Server::Server
- Includes:
- UnixDaemon
- Defined in:
- lib/acts_as_ferret/server/server.rb
Overview
This class acts as a drb server listening for indexing and search requests from models declared to ‘acts_as_ferret :remote => true’
Usage:
-
modify Rails.root/config/ferret_server.yml to suit your needs.
-
environments for which no section in the config file exists will use the index locally (good for unit tests/development mode)
-
run script/ferret_server to start the server:
script/ferret_server -e production start
-
to stop the server run
script/ferret_server -e production stop
Instance Method Summary collapse
-
#db_disconnect!(class_name) ⇒ Object
disconnects the db connection for the class specified by class_name used only in unit tests to check the automatic reconnection feature.
-
#ensure_index_exists(index_name) ⇒ Object
make sure we have a versioned index in place, building one if necessary.
-
#initialize ⇒ Server
constructor
A new instance of Server.
-
#method_missing(name, *args) ⇒ Object
handles all incoming method calls, and sends them on to the correct local index instance.
-
#rebuild_index(index_name) ⇒ Object
hides LocalIndex#rebuild_index to implement index versioning.
- #register_class(class_name) ⇒ Object
-
#run ⇒ Object
run the server and block until it exits.
- #run_drb_service ⇒ Object
-
#start ⇒ Object
start the server as a daemon process.
Methods included from UnixDaemon
#ensure_stopped, #platform_daemon, #process_exists, #read_pid_file, #safefork, #stop, #write_pid_file
Constructor Details
#initialize ⇒ Server
Returns a new instance of Server.
29 30 31 32 33 34 35 36 37 38 |
# File 'lib/acts_as_ferret/server/server.rb', line 29 def initialize @cfg = Config.new ActiveRecord::Base.logger = @logger = Logger.new(@cfg.log_file) ActiveRecord::Base.logger.level = Logger.const_get(@cfg.log_level.upcase) rescue Logger::DEBUG if @cfg.script path = File.join(Rails.root, @cfg.script) load path @logger.info "loaded custom startup script from #{path}" end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args) ⇒ Object
handles all incoming method calls, and sends them on to the correct local index instance.
Calls are not queued, so this will block until the call returned.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/acts_as_ferret/server/server.rb', line 67 def method_missing(name, *args) @logger.debug "\#method_missing(#{name.inspect}, #{args.inspect})" index_name = args.shift index = if name.to_s =~ /^multi_(.+)/ name = $1 ActsAsFerret::multi_index(index_name) else ActsAsFerret::get_index(index_name) end if index.nil? @logger.error "\#index with name #{index_name} not found in call to #{name} with args #{args.inspect}" raise ActsAsFerret::IndexNotDefined.new(index_name) end # TODO find another way to implement the reconnection logic (maybe in # local_index or class_methods) # reconnect_when_needed(clazz) do # using respond_to? here so we not have to catch NoMethodError # which would silently catch those from deep inside the indexing # code, too... if index.respond_to?(name) index.send name, *args # TODO check where we need this: #elsif clazz.respond_to?(name) # @logger.debug "no luck, trying to call class method instead" # clazz.send name, *args else raise NoMethodError.new("method #{name} not supported by DRb server") end rescue => e @logger.error "ferret server error #{$!}\n#{$!.backtrace.join "\n"}" raise e end |
Instance Method Details
#db_disconnect!(class_name) ⇒ Object
disconnects the db connection for the class specified by class_name used only in unit tests to check the automatic reconnection feature
126 127 128 129 130 |
# File 'lib/acts_as_ferret/server/server.rb', line 126 def db_disconnect!(class_name) with_class class_name do |clazz| clazz.connection.disconnect! end end |
#ensure_index_exists(index_name) ⇒ Object
make sure we have a versioned index in place, building one if necessary
115 116 117 118 119 120 121 122 |
# File 'lib/acts_as_ferret/server/server.rb', line 115 def ensure_index_exists(index_name) @logger.debug "DRb server: ensure_index_exists for index #{index_name}" definition = ActsAsFerret::get_index(index_name).index_definition dir = definition[:index_dir] unless File.directory?(dir) && File.file?(File.join(dir, 'segments')) && dir =~ %r{/\d+(_\d+)?$} rebuild_index(index_name) end end |
#rebuild_index(index_name) ⇒ Object
hides LocalIndex#rebuild_index to implement index versioning
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/acts_as_ferret/server/server.rb', line 133 def rebuild_index(index_name) definition = ActsAsFerret::get_index(index_name).index_definition.dup models = definition[:registered_models] index = new_index_for(definition) # TODO fix reconnection stuff # reconnect_when_needed(clazz) do # @logger.debug "DRb server: rebuild index for class(es) #{models.inspect} in #{index.options[:path]}" index.index_models models # end new_version = File.join definition[:index_base_dir], Time.now.utc.strftime('%Y%m%d%H%M%S') # create a unique directory name (needed for unit tests where # multiple rebuilds per second may occur) if File.exists?(new_version) i = 0 i+=1 while File.exists?("#{new_version}_#{i}") new_version << "_#{i}" end File.rename index.[:path], new_version ActsAsFerret::change_index_dir index_name, new_version end |
#register_class(class_name) ⇒ Object
107 108 109 110 111 112 |
# File 'lib/acts_as_ferret/server/server.rb', line 107 def register_class(class_name) @logger.debug "############ registerclass #{class_name}" class_name.constantize @logger.debug "index for class #{class_name}: #{ActsAsFerret::ferret_indexes[class_name.underscore.to_sym]}" end |
#run ⇒ Object
run the server and block until it exits
47 48 49 50 |
# File 'lib/acts_as_ferret/server/server.rb', line 47 def run raise "ferret_server not configured for #{Rails.env}" unless (@cfg.uri rescue nil) run_drb_service end |
#run_drb_service ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'lib/acts_as_ferret/server/server.rb', line 52 def run_drb_service $stdout.puts("starting ferret server...") self.class.running = true DRb.start_service(@cfg.uri, self) DRb.thread.join rescue Exception => e @logger.error(e.to_s) raise end |
#start ⇒ Object
start the server as a daemon process
41 42 43 44 |
# File 'lib/acts_as_ferret/server/server.rb', line 41 def start raise "ferret_server not configured for #{Rails.env}" unless (@cfg.uri rescue nil) platform_daemon { run_drb_service } end |