lib/flapjack/coordinator.rb in flapjack-0.8.1 vs lib/flapjack/coordinator.rb in flapjack-0.8.2

- old
+ new

@@ -19,34 +19,53 @@ def initialize(config) @config = config @redis_options = config.for_redis @pikelets = [] + @received_signals = [] + @logger = Flapjack::Logger.new("flapjack-coordinator", @config.all['logger']) end def start(options = {}) @boot_time = Time.now EM.synchrony do setup_signals if options[:signals] - add_pikelets(pikelets(@config.all)) + + begin + add_pikelets(pikelets(@config.all)) + loop do + while sig = @received_signals.shift do + case sig + when 'INT', 'TERM', 'QUIT' + @exit_value = Signal.list[sig] + 128 + raise Interrupt + when 'HUP' + reload + end + end + EM::Synchrony.sleep 0.25 + end + rescue Exception => e + unless e.is_a?(Interrupt) + trace = e.backtrace.join("\n") + @logger.fatal "#{e.class.name}\n#{e.message}\n#{trace}" + @exit_value = 1 + end + remove_pikelets(@pikelets) + EM.stop + end end + Syslog.close if Syslog.opened? + @exit_value end - def stop(value = 0) - return unless @exit_value.nil? - @exit_value = value - remove_pikelets(@pikelets, :shutdown => true) - # Syslog.close if Syslog.opened? # TODO revisit in threading branch - end + private - # NB: global config options (e.g. daemonize, pidfile, - # logfile, redis options) won't be checked on reload. - # should we do a full restart if some of these change? def reload prev_pikelet_cfg = pikelets(@config.all) removed = [] added = [] @@ -83,88 +102,64 @@ next unless pik.reload(enabled_pikelet_cfg[pik.type]).is_a?(FalseClass) removed << pik.type added << pik.type end - # puts "removed" - # p removed - - # puts "added" - # p added - removed_pikelets = @pikelets.select {|pik| removed.include?(pik.type) } - # puts "removed pikelets" - # p removed_pikelets - remove_pikelets(removed_pikelets) # is there a nicer way to only keep the parts of the hash with matching keys? added_pikelets = enabled_pikelet_cfg.select {|k, v| added.include?(k) } - # puts "added pikelet configs" - # p added_pikelets - add_pikelets(added_pikelets) end - private - # the global nature of this seems at odds with it calling stop # within a single coordinator instance. Coordinator is essentially # a singleton anyway... def setup_signals - Kernel.trap('INT') { stop(Signal.list['INT']) } - Kernel.trap('TERM') { stop(Signal.list['TERM']) } + Kernel.trap('INT') { @received_signals << 'INT' unless @received_signals.include?('INT') } + Kernel.trap('TERM') { @received_signals << 'TERM' unless @received_signals.include?('TERM') } unless RbConfig::CONFIG['host_os'] =~ /mswin|windows|cygwin/i - Kernel.trap('QUIT') { stop(Signal.list['QUIT']) } - Kernel.trap('HUP') { reload } + Kernel.trap('QUIT') { @received_signals << 'QUIT' unless @received_signals.include?('QUIT') } + Kernel.trap('HUP') { @received_signals << 'HUP' unless @received_signals.include?('HUP') } end end # passed a hash with {PIKELET_TYPE => PIKELET_CFG, ...} def add_pikelets(pikelets_data = {}) - start_piks = [] pikelets_data.each_pair do |type, cfg| next unless pikelet = Flapjack::Pikelet.create(type, - :config => cfg, :redis_config => @redis_options, :boot_time => @boot_time, :coordinator => self) - start_piks << pikelet + :config => cfg, :redis_config => @redis_options, + :boot_time => @boot_time) + @pikelets << pikelet + pikelet.start end - begin - start_piks.each {|pik| pik.start } - rescue Exception => e - trace = e.backtrace.join("\n") - @logger.fatal "#{e.class.name}\n#{e.message}\n#{trace}" - stop - end end def remove_pikelets(piks, opts = {}) - Fiber.new { - piks.map(&:stop) + piks.map(&:stop) - loop do - # only prints state changes, otherwise pikelets not closing promptly can - # cause everything else to be spammy - piks.each do |pik| - old_status = pik.status - pik.update_status - status = pik.status - next if old_status.eql?(status) - # # can't log on exit w/Ruby 2.0 - # @logger.info "#{pik.type}: #{old_status} -> #{status}" - end + loop do + # only prints state changes, otherwise pikelets not closing promptly can + # cause everything else to be spammy + piks.each do |pik| + old_status = pik.status + pik.update_status + status = pik.status + next if old_status.eql?(status) + @logger.info "#{pik.type}: #{old_status} -> #{status}" + end - if piks.any? {|p| p.status == 'stopping' } - EM::Synchrony.sleep 0.25 - else - EM.stop if opts[:shutdown] - @pikelets -= piks - break - end + if piks.any? {|p| p.status == 'stopping' } + EM::Synchrony.sleep 0.25 + else + @pikelets -= piks + break end - }.resume + end end def pikelets(config_env) config = {} return config unless config_env