lib/picky/interfaces/live_parameters.rb in picky-2.7.0 vs lib/picky/interfaces/live_parameters.rb in picky-3.0.0.pre1

- old
+ new

@@ -1,182 +1,187 @@ -# This is very optional. -# Only load if the user wants it. -# -module Interfaces - # This is an interface that provides the user of - # Picky with the possibility to change parameters - # while the Application is running. +module Picky + + # This is very optional. + # Only load if the user wants it. # - # Important Note: This will only work in Master/Child configurations. - # - class LiveParameters + module Interfaces - def initialize - @child, @parent = IO.pipe - start_master_process_thread - end - - # This runs a thread that listens to child processes. + # This is an interface that provides the user of + # Picky with the possibility to change parameters + # while the Application is running. # - def start_master_process_thread - # This thread is stopped in the children. + # Important Note: This will only work in Master/Child configurations. + # + class LiveParameters + + def initialize + @child, @parent = IO.pipe + start_master_process_thread + end + + # This runs a thread that listens to child processes. # - Thread.new do - loop do - IO.select([@child], nil, nil, 2) or next - result = @child.gets ';;;' - pid, configuration_hash = eval result - next unless Hash === configuration_hash - next if configuration_hash.empty? - exclaim "Trying to update MASTER configuration." - try_updating_configuration_with configuration_hash - kill_each_worker_except pid + def start_master_process_thread + # This thread is stopped in the children. + # + Thread.new do + loop do + IO.select([@child], nil, nil, 2) or next + result = @child.gets ';;;' + pid, configuration_hash = eval result + next unless Hash === configuration_hash + next if configuration_hash.empty? + exclaim "Trying to update MASTER configuration." + try_updating_configuration_with configuration_hash + kill_each_worker_except pid - # Fails hard on an error. - # + # Fails hard on an error. + # + end end end - end - # TODO This needs to be webserver agnostic. - # - def worker_pids - Unicorn::HttpServer::WORKERS.keys - end + # TODO This needs to be webserver agnostic. + # + def worker_pids + Unicorn::HttpServer::WORKERS.keys + end - # Taken from Unicorn. - # - def kill_each_worker_except pid - worker_pids.each do |wpid| - next if wpid == pid - kill_worker :KILL, wpid + # Taken from Unicorn. + # + def kill_each_worker_except pid + worker_pids.each do |wpid| + next if wpid == pid + kill_worker :KILL, wpid + end end - end - def kill_worker signal, wpid - Process.kill signal, wpid - exclaim "Killing worker ##{wpid} with signal #{signal}." - rescue Errno::ESRCH - remove_worker wpid - end - # TODO This needs to be Webserver agnostic. - # - def remove_worker wpid - worker = Unicorn::HttpServer::WORKERS.delete(wpid) and worker.tmp.close rescue nil - end + def kill_worker signal, wpid + Process.kill signal, wpid + exclaim "Killing worker ##{wpid} with signal #{signal}." + rescue Errno::ESRCH + remove_worker wpid + end + # TODO This needs to be Webserver agnostic. + # + def remove_worker wpid + worker = Unicorn::HttpServer::WORKERS.delete(wpid) and worker.tmp.close rescue nil + end - # Updates any parameters with the ones given and - # returns the updated params. - # - # The params are a strictly defined hash of: - # * querying_removes_characters: Regexp - # * querying_stopwords: Regexp - # * querying_splits_text_on: Regexp - # - # This first tries to update in the child process, - # and if successful, in the parent process - # - def parameters configuration_hash - close_child - exclaim "Trying to update worker child configuration." unless configuration_hash.empty? - try_updating_configuration_with configuration_hash - write_parent configuration_hash - extract_configuration - rescue CouldNotUpdateConfigurationError => e - # I need to die such that my broken config is never used. + # Updates any parameters with the ones given and + # returns the updated params. # - exclaim "Child process #{Process.pid} performs harakiri because of broken config." - harakiri - { e.config_key => :ERROR } - end - # Kills itself, but still answering the request honorably. - # - def harakiri - Process.kill :QUIT, Process.pid - end - # Write the parent. - # - # Note: The ;;; is the end marker for the message. - # - def write_parent configuration_hash - @parent.write "#{[Process.pid, configuration_hash]};;;" - end - # Close the child if it isn't yet closed. - # - def close_child - @child.close unless @child.closed? - end + # The params are a strictly defined hash of: + # * querying_removes_characters: Regexp + # * querying_stopwords: Regexp + # * querying_splits_text_on: Regexp + # + # This first tries to update in the child process, + # and if successful, in the parent process + # + def parameters configuration_hash + close_child + exclaim "Trying to update worker child configuration." unless configuration_hash.empty? + try_updating_configuration_with configuration_hash + write_parent configuration_hash + extract_configuration + rescue CouldNotUpdateConfigurationError => e + # I need to die such that my broken config is never used. + # + exclaim "Child process #{Process.pid} performs harakiri because of broken config." + harakiri + { e.config_key => :ERROR } + end + # Kills itself, but still answering the request honorably. + # + def harakiri + Process.kill :QUIT, Process.pid + end + # Write the parent. + # + # Note: The ;;; is the end marker for the message. + # + def write_parent configuration_hash + @parent.write "#{[Process.pid, configuration_hash]};;;" + end + # Close the child if it isn't yet closed. + # + def close_child + @child.close unless @child.closed? + end - class CouldNotUpdateConfigurationError < StandardError - attr_reader :config_key - def initialize config_key, message - super message - @config_key = config_key + class CouldNotUpdateConfigurationError < StandardError + attr_reader :config_key + def initialize config_key, message + super message + @config_key = config_key + end end - end - # Tries updating the configuration in the child process or parent process. - # - def try_updating_configuration_with configuration_hash - current_key = nil - begin - configuration_hash.each_pair do |key, new_value| - exclaim " Setting #{key} with #{new_value}." - current_key = key - send :"#{key}=", new_value + # Tries updating the configuration in the child process or parent process. + # + def try_updating_configuration_with configuration_hash + current_key = nil + begin + configuration_hash.each_pair do |key, new_value| + exclaim " Setting #{key} with #{new_value}." + current_key = key + send :"#{key}=", new_value + end + rescue StandardError => e + # Catch any error and reraise as config error. + # + raise CouldNotUpdateConfigurationError.new current_key, e.message end - rescue StandardError => e - # Catch any error and reraise as config error. - # - raise CouldNotUpdateConfigurationError.new current_key, e.message end - end - def extract_configuration - { - querying_removes_characters: querying_removes_characters, - querying_stopwords: querying_stopwords, - querying_splits_text_on: querying_splits_text_on - } - end + def extract_configuration + { + querying_removes_characters: querying_removes_characters, + querying_stopwords: querying_stopwords, + querying_splits_text_on: querying_splits_text_on + } + end - # TODO Move to Interface object. - # - def querying_removes_characters - regexp = Tokenizers::Query.default.instance_variable_get :@removes_characters_regexp - regexp && regexp.source - end - def querying_removes_characters= new_value - Tokenizers::Query.default.instance_variable_set(:@removes_characters_regexp, %r{#{new_value}}) - end - def querying_stopwords - regexp = Tokenizers::Query.default.instance_variable_get :@remove_stopwords_regexp - regexp && regexp.source - end - def querying_stopwords= new_value - Tokenizers::Query.default.instance_variable_set(:@remove_stopwords_regexp, %r{#{new_value}}) - end - def querying_splits_text_on - splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on - splits && splits.respond_to?(:source) ? splits.source : splits - end - def querying_splits_text_on= new_value - splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on - if splits.respond_to?(:source) - Tokenizers::Query.default.instance_variable_set(:@splits_text_on, %r{#{new_value}}) - else - Tokenizers::Query.default.instance_variable_set(:@splits_text_on, new_value) + # TODO Move to Interface object. + # + def querying_removes_characters + regexp = Tokenizers::Query.default.instance_variable_get :@removes_characters_regexp + regexp && regexp.source end - end + def querying_removes_characters= new_value + Tokenizers::Query.default.instance_variable_set(:@removes_characters_regexp, %r{#{new_value}}) + end + def querying_stopwords + regexp = Tokenizers::Query.default.instance_variable_get :@remove_stopwords_regexp + regexp && regexp.source + end + def querying_stopwords= new_value + Tokenizers::Query.default.instance_variable_set(:@remove_stopwords_regexp, %r{#{new_value}}) + end + def querying_splits_text_on + splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on + splits && splits.respond_to?(:source) ? splits.source : splits + end + def querying_splits_text_on= new_value + splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on + if splits.respond_to?(:source) + Tokenizers::Query.default.instance_variable_set(:@splits_text_on, %r{#{new_value}}) + else + Tokenizers::Query.default.instance_variable_set(:@splits_text_on, new_value) + end + end - # - # - def to_s - "Suckerfish Live Interface (Use the picky-live gem to introspect)" + # + # + def to_s + "Suckerfish Live Interface (Use the picky-live gem to introspect)" + end + end end # Aka. # - ::LiveParameters = LiveParameters + LiveParameters = Interfaces::LiveParameters end \ No newline at end of file