Class: ActsAsFerret::Remote::Server
- Inherits:
-
Object
- Object
- ActsAsFerret::Remote::Server
- Includes:
- UnixDaemon
- Defined in:
- lib/ferret_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.
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ferret_server.rb', line 69 def initialize ActiveRecord::Base.allow_concurrency = true require 'ar_mysql_auto_reconnect_patch' @cfg = ActsAsFerret::Remote::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.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/ferret_server.rb', line 112 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
171 172 173 174 175 |
# File 'lib/ferret_server.rb', line 171 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
160 161 162 163 164 165 166 167 |
# File 'lib/ferret_server.rb', line 160 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
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/ferret_server.rb', line 178 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
152 153 154 155 156 157 |
# File 'lib/ferret_server.rb', line 152 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
91 92 93 94 |
# File 'lib/ferret_server.rb', line 91 def run raise "ferret_server not configured for #{RAILS_ENV}" unless (@cfg.uri rescue nil) run_drb_service end |
#run_drb_service ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/ferret_server.rb', line 96 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
84 85 86 87 |
# File 'lib/ferret_server.rb', line 84 def start raise "ferret_server not configured for #{RAILS_ENV}" unless (@cfg.uri rescue nil) platform_daemon { run_drb_service } end |