Class: Blessing::Leader

Inherits:
Object
  • Object
show all
Defined in:
lib/blessing/leader.rb

Overview

Blessing::Leader is the main class and entry point

Constant Summary collapse

DefaultOptions =
{
  # Run as daemon
  :daemonize => false,
  # Monitoring refresh cycle legth in seconds
  :refresh => 10,
  :verbose => false,
  :log => STDOUT,
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(patterns, opts = {}) ⇒ Leader

Initialize new Blessing::Leader with file list pattern



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/blessing/leader.rb', line 21

def initialize patterns, opts = {}
  @options = DefaultOptions.merge(opts)
  @mutex = Monitor.new

  initialize_logger

  logger.info "Starting Blessing::Leader"
  @patterns = patterns.is_a?(Array) ? patterns : [patterns]
  logger.debug "Patterns: #{patterns.inspect}"

  @old_confdig_files = @config_files = []
  @runners = {}

  # Trap some signals
  trap("INT"){
    logger.info "Caught SIGINT"
    at_exit
  }
  trap("TERM"){
    logger.info "Caught SIGTERM"
    at_exit
  }
  trap("USR1"){
    # Rerun cycle
    run_cycle
  }
  trap("USR2"){
    # resurrect dead Unicorns!
    run_cycle(true)
  }
end

Instance Attribute Details

#config_filesObject

Returns the value of attribute config_files.



18
19
20
# File 'lib/blessing/leader.rb', line 18

def config_files
  @config_files
end

#loggerObject

Returns the value of attribute logger.



18
19
20
# File 'lib/blessing/leader.rb', line 18

def logger
  @logger
end

#old_config_filesObject

Returns the value of attribute old_config_files.



18
19
20
# File 'lib/blessing/leader.rb', line 18

def old_config_files
  @old_config_files
end

#patternsObject

Returns the value of attribute patterns.



18
19
20
# File 'lib/blessing/leader.rb', line 18

def patterns
  @patterns
end

#runnersObject

Returns the value of attribute runners.



18
19
20
# File 'lib/blessing/leader.rb', line 18

def runners
  @runners
end

Instance Method Details

#at_exitObject

Daemons hook to shut down properly



59
60
61
62
# File 'lib/blessing/leader.rb', line 59

def at_exit
  logger.info "Shutting down"
  stop
end

#initialize_loggerObject



53
54
55
56
# File 'lib/blessing/leader.rb', line 53

def initialize_logger
  @logger = Logger.new @options[:log]
  @logger.level = @options[:verbose] ? Logger::DEBUG : Logger::INFO
end

#refresh_file_listObject

Refresh config file list and preserve old list



105
106
107
108
109
110
111
112
113
114
# File 'lib/blessing/leader.rb', line 105

def refresh_file_list
  logger.debug "Refreshing file list"
  # Preserve old file list
  @old_config_files = @config_files

  files = []
  @patterns.each{|p| files += Dir.glob(p)}
  @config_files = files.uniq.sort
  logger.debug "Found files: #{@config_files.inspect}"
end

#reload_runners(resurrect = false) ⇒ Object

Let each runner check itself if reload is needed



145
146
147
148
149
# File 'lib/blessing/leader.rb', line 145

def reload_runners(resurrect=false)
  @runners.each_value do |runner|
    runner.check_reload(resurrect)
  end
end

#run_cycle(resurrect = false) ⇒ Object

Main cycle

  • refresh file list

  • start/stop runners

  • verify/reload runners



95
96
97
98
99
100
101
102
# File 'lib/blessing/leader.rb', line 95

def run_cycle(resurrect=false)
  @mutex.synchronize do
    logger.debug "Next cycle"
    refresh_file_list
    start_stop_runners
    reload_runners(resurrect)
  end
end

#startObject

Start running cycles



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/blessing/leader.rb', line 65

def start
  logger.info "Starting cycles"
  @run_cycles = true
  while @run_cycles do
    run_cycle
    sleep @options[:refresh]
  end
rescue => e
  if logger && logger.respond_to?(:fatal)
    logger.fatal "FATAL ERROR: Unexpected error: #{e}"
    logger.fatal e.backtrace.join("\n")
  end
  # Reraise the exception in case somebody else catches it
  raise e
end

#start_runners(files) ⇒ Object

Start runners for added config files



125
126
127
128
129
130
131
# File 'lib/blessing/leader.rb', line 125

def start_runners(files)
  logger.debug "Starting runners for: #{files.inspect}" unless files.empty?
  files.each { |conf|
    @runners[conf] = runner = Blessing::Runner.new(conf, :leader => self)
    runner.start
  }
end

#start_stop_runnersObject

Find differences in old and new config file lists and start/stop runners as appropriate



118
119
120
121
# File 'lib/blessing/leader.rb', line 118

def start_stop_runners
  start_runners @config_files - @old_config_files
  stop_runners @old_config_files - @config_files
end

#stopObject

Stop running cycles



82
83
84
85
86
87
88
89
# File 'lib/blessing/leader.rb', line 82

def stop
  @mutex.synchronize do
    @run_cycles = false
    logger.debug "Stopping all runners..."
    stop_runners @config_files
    logger.info "All runners stopped. Exiting..."
  end
end

#stop_runners(files) ⇒ Object

Stop runners for missing config files



134
135
136
137
138
139
140
141
142
# File 'lib/blessing/leader.rb', line 134

def stop_runners(files)
  logger.debug "Stopping runners for: #{files.inspect}" unless files.empty?
  files.each { |conf| 
    if @runners[conf]
      @runners[conf].stop
      @runners.delete(conf)
    end
  }
end