lib/asir/main.rb in asir-0.2.0 vs lib/asir/main.rb in asir-1.0.1

- old
+ new

@@ -1,43 +1,38 @@ require 'asir' +require 'asir/environment' require 'time' - module ASIR class Main - attr_accessor :verb, :adjective, :object, :identifier - attr_accessor :config_rb, :config - attr_accessor :log_dir, :pid_dir - attr_accessor :verbose - attr_accessor :exit_code + attr_accessor :env, :args, :exit_code + # Delegate getter/setters to @env. + [ :verb, :adjective, :object, :identifier, + :config_rb, + :verbose, + :log_dir, :log_file, + :pid_dir, :pid_file, + ]. + map{|g| [ g, :"#{g}=" ]}. + flatten.each do | m | + define_method(m) { | *args | @env.send(m, *args) } + end + attr_accessor :progname + # Options: + attr_accessor :force + # Transport selected from asir.phase = :transport. + attr_accessor :transport + def initialize - @verbose = 0 - @progname = File.basename($0) - @log_dir = find_writable_directory :log_dir, - ENV['ASIR_LOG_DIR'], - '/var/log/asir', - '~/asir/log', - '/tmp' - @pid_dir = find_writable_directory :pid_dir, - ENV['ASIR_PID_DIR'], - '/var/run/asir', - '~/asir/run', - '/tmp' - @exit_code = 0 + self.env = ASIR::Environment.new + self.progname = File.basename($0) + self.exit_code = 0 end - def find_writable_directory kind, *list - list. - reject { | p | ! p }. - map { | p | File.expand_path(p) }. - find { | p | File.writable?(p) } or - raise "Cannot find writable directory for #{kind}" - end - def parse_args! args = ARGV.dup - @args = args + self.args = args until args.empty? case args.first when /^([a-z0-9_]+=)(.*)/i k, v = $1.to_sym, $2 args.shift @@ -45,29 +40,33 @@ send(k, v) else break end end - @verb, @adjective, @object, @identifier = args.map{|x| x.to_sym} - @identifier ||= :'0' + self.verb, self.adjective, self.object, self.identifier = args.map{|x| x.to_sym} + self.identifier ||= :'0' self end + def config! *args + @env.config! *args + end + def log_str "#{Time.now.gmtime.iso8601(4)} #{$$} #{log_str_no_time}" end def log_str_no_time - "#{@progname} #{@verb} #{@adjective} #{@object} #{@identifier}" + "#{progname} #{verb} #{adjective} #{object} #{identifier}" end def run! unless verb && adjective && object - @exit_code = 1 + self.exit_code = 1 return usage! end - config!(:config) + config!(:configure) # $stderr.puts "log_file = #{log_file.inspect}" case self.verb when :restart self.verb = :stop _run_verb! && sleep(1) @@ -77,32 +76,32 @@ _run_verb! end self rescue ::Exception => exc $stderr.puts "#{log_str} ERROR\n#{exc.inspect}\n #{exc.backtrace * "\n "}" - @exit_code += 1 + self.exit_code += 1 self end def _run_verb! sel = :"#{verb}_#{adjective}_#{object}!" - if @verbose >= 3 - $stderr.puts "verb = #{verb.inspect}" - $stderr.puts "adjective = #{adjective.inspect}" - $stderr.puts "object = #{object.inspect}" - $stderr.puts "sel = #{sel.inspect}" + if verbose >= 3 + $stderr.puts " verb = #{verb.inspect}" + $stderr.puts " adjective = #{adjective.inspect}" + $stderr.puts " object = #{object.inspect}" + $stderr.puts " sel = #{sel.inspect}" end send(sel) rescue ::Exception => exc $stderr.puts "#{log_str} ERROR\n#{exc.inspect}\n #{exc.backtrace * "\n "}" - @exit_code += 1 + self.exit_code += 1 raise nil end def method_missing sel, *args - log "method_missing #{sel}" if @verbose >= 3 + log "method_missing #{sel}" if verbose >= 3 case sel.to_s when /^start_([^_]+)_worker!$/ _start_worker! when /^status_([^_]+)_([^_]+)!$/ pid = server_pid @@ -111,11 +110,18 @@ when /^log_([^_]+)_([^_]+)!$/ puts log_file when /^taillog_([^_]+)_([^_]+)!$/ exec "tail -f #{log_file.inspect}" when /^pid_([^_]+)_([^_]+)!$/ - puts "#{pid_file} #{File.read(pid_file) rescue nil}" + pid = server_pid rescue nil + alive = process_running? pid + puts "#{pid_file} #{pid || :NA} #{alive}" + when /^alive_([^_]+)_([^_]+)!$/ + pid = server_pid rescue nil + alive = process_running? pid + puts "#{pid_file} #{pid || :NA} #{alive}" if @verbose + self.exit_code += 1 unless alive when /^stop_([^_]+)_([^_]+)!$/ kill_server! else super end @@ -137,24 +143,28 @@ stop restart status log pid + alive ADJECTIVE-OBJECTs: beanstalk conduit beanstalk worker zmq worker webrick worker + resque conduit + resque worker EXAMPLES: export ASIR_CONFIG_RB="some_system/asir_config.rb" asir start beanstalk conduit asir status beanstalk conduit asir start webrick worker + asir pid webrick worker asir start beanstalk worker 1 asir start beanstalk worker 2 asir start zmq worker @@ -162,13 +172,25 @@ asir start zmq worker 2 END end def start_beanstalk_conduit! - fork_server! "beanstalkd" + _start_conduit! end + def start_resque_conduit! + _start_conduit! + end + + def _start_conduit! + config!(:environment) + self.transport = config!(:transport) + fork_server! do + transport.start_conduit! :fork => false + end + end + def _start_worker! type = adjective log "start_worker! #{type}" type = type.to_s fork_server! do transport_file = "asir/transport/#{type}" @@ -177,58 +199,10 @@ _create_transport ASIR::Transport.const_get(type[0..0].upcase + type[1..-1]) _run_workers! end end - ################################################################ - - def config_rb - @config_rb ||= - File.expand_path(ENV['ASIR_CONFIG_RB'] || 'config/asir_config.rb') - end - - def config_lambda - @config_lambda ||= - begin - file = config_rb - $stderr.puts "#{log_str} loading #{file} ..." if @verbose >= 1 - expr = File.read(file) - expr = "begin; lambda do | asir |; #{expr}\n end; end" - cfg = Object.new.send(:eval, expr, binding, file, 1) - # cfg = load file - # $stderr.puts "#{log_str} loading #{file} DONE" if @verbose >= 1 - raise "#{file} did not return a Proc, returned a #{cfg.class}" unless Proc === cfg - cfg - end - end - - def config! verb = @verb - (@config ||= { })[verb] ||= - begin - save_verb = @verb - @verb = verb - $stderr.puts "#{log_str} calling #{config_rb} asir.verb=#{@verb.inspect} ..." if @verbose >= 1 - cfg = config_lambda.call(self) - $stderr.puts "#{log_str} calling #{config_rb} asir.verb=#{@verb.inspect} DONE" if @verbose >= 1 - cfg - ensure - @verb = save_verb - end - end - - def pid_file - "#{pid_dir}/#{asir_basename}.pid" - end - - def log_file - "#{log_dir}/#{asir_basename}.log" - end - - def asir_basename - "asir-#{adjective}-#{object}-#{identifier}" - end - def fork_server! cmd = nil, &blk pid = Process.fork do run_server! cmd, &blk end log "forked pid #{pid}" @@ -299,26 +273,26 @@ def _create_transport default_class config!(:environment) case transport = config!(:transport) when default_class - @transport = transport + self.transport = transport else raise "Expected config to return a #{default_class}, not a #{transport.class}" end end def worker_pids - (@worker_pids ||= { })[@adjective] ||= { } + (@worker_pids ||= { })[adjective] ||= { } end def _run_workers! - $0 = "#{@progname} #{@adjective} #{@object} #{@identifier}" + $0 = "#{progname} #{adjective} #{object} #{identifier}" worker_id = 0 - @transport.prepare_server! - worker_processes = @transport[:worker_processes] || 1 + transport.prepare_server! + worker_processes = transport[:worker_processes] || 1 (worker_processes - 1).times do wid = worker_id += 1 pid = Process.fork do _run_transport_server! wid end @@ -332,20 +306,20 @@ log "worker 0 stopped" _stop_workers! end def _run_transport_server! wid = 0 - log "running transport worker #{@transport.class} #{wid}" + log "running transport worker #{transport.class} #{wid}" config!(:start) - $0 += " #{wid} #{@transport.uri rescue nil}" + $0 += " #{wid} #{transport.uri rescue nil}" old_arg0 = $0.dup - after_receive_message = @transport.after_receive_message || lambda { | transport, message | nil } - @transport.after_receive_message = lambda do | transport, message | + after_receive_message = transport.after_receive_message || lambda { | transport, message | nil } + transport.after_receive_message = lambda do | transport, message | $0 = "#{old_arg0} #{transport.message_count} #{message.identifier}" after_receive_message.call(transport, message) end - @transport.run_server! + transport.run_server! self end def _stop_workers! workers = worker_pids.dup @@ -366,11 +340,11 @@ log "stopping #{msg}pid #{pid}", :stderr if process_running? pid log "TERM pid #{pid}" Process.kill('TERM', pid) rescue nil sleep 3 - if @force or process_running? pid + if force or process_running? pid log "KILL pid #{pid}", :stderr Process.kill('KILL', pid) rescue nil end if process_running? pid log "cant-stop pid #{pid}", :stderr @@ -379,10 +353,17 @@ log "not-running? pid #{pid}", :stderr end end def process_running? pid - Process.kill(0, pid) + case pid + when false, nil + pid + when Integer + Process.kill(0, pid) + else + raise TypeError, "expected false, nil, Integer; given #{pid.inspect}" + end true rescue ::Errno::ESRCH false rescue ::Exception => exc $stderr.puts " DEBUG: process_running? #{pid} => #{exc.inspect}"