1 $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
9 require 'god/system/process'
11 require 'god/dependency_graph'
13 require 'god/behavior'
14 require 'god/behaviors/clean_pid_file'
15 require 'god/behaviors/notify_when_flapping'
17 require 'god/condition'
18 require 'god/conditions/timeline'
19 require 'god/conditions/process_running'
20 require 'god/conditions/process_exits'
21 require 'god/conditions/tries'
22 require 'god/conditions/memory_usage'
23 require 'god/conditions/cpu_usage'
24 require 'god/conditions/always'
25 require 'god/conditions/lambda'
26 require 'god/conditions/degrading_lambda'
28 require 'god/reporter'
36 require 'god/event_handler'
37 require 'god/registry'
42 $:.unshift File.join(File.dirname(__FILE__), *%w[.. ext god])
50 God::EventHandler.load
56 attr_accessor :inited, :running, :pending_watches, :host, :port
62 attr_accessor :watches, :groups
67 abort "God.init must be called before any Watches"
73 def self.internal_init
80 self.pending_watches = []
82 # yield to the config file
83 yield self if block_given?
86 self.server = Server.new(self.host, self.port)
88 # init has been executed
95 # Where pid files created by god will go by default
96 def self.pid_file_directory
97 @pid_file_directory ||= '/var/run/god'
100 def self.pid_file_directory=(value)
101 @pid_file_directory = value
104 # Instantiate a new, empty Watch object and pass it to the mandatory
105 # block. The attributes of the watch will be set by the configuration
113 # if running, completely remove the watch (if necessary) to
114 # prepare for the reload
115 existing_watch = self.watches[w.name]
116 if self.running && existing_watch
117 self.unwatch(existing_watch)
120 # ensure the new watch has a unique name
121 if self.watches[w.name] || self.groups[w.name]
122 abort "Watch name '#{w.name}' already used for a Watch or Group"
125 # ensure watch is internally valid
126 w.valid? || abort("Watch '#{w.name}' is not valid (see above)")
128 # add to list of watches
129 self.watches[w.name] = w
131 # add to pending watches
132 self.pending_watches << w
134 # add to group if specified
136 # ensure group name hasn't been used for a watch already
137 if self.watches[w.group]
138 abort "Group name '#{w.group}' already used for a Watch"
141 self.groups[w.group] ||= []
142 self.groups[w.group] << w
149 def self.unwatch(watch)
156 # remove from watches
157 self.watches.delete(watch.name)
161 self.groups[watch.group].delete(watch)
165 def self.control(name, command)
166 # get the list of watches
167 watches = Array(self.watches[name] || self.groups[name])
171 when "start", "monitor"
172 watches.each { |w| w.monitor }
174 watches.each { |w| w.move(:restart) }
176 watches.each { |w| w.unmonitor.action(:stop) }
178 watches.each { |w| w.unmonitor }
180 raise InvalidCommandError.new
186 def self.running_load(code)
188 self.pending_watches.each { |w| w.monitor if w.autostart? }
189 watches = self.pending_watches.dup
190 self.pending_watches.clear
195 Dir[glob].each do |f|
201 # make sure there's something to do
202 if self.watches.nil? || self.watches.empty?
203 abort "You must specify at least one watch!"
206 # start event handler system
207 EventHandler.start if EventHandler.loaded?
209 # start the timer system
212 # start monitoring any watches set to autostart
213 self.watches.values.each { |w| w.monitor if w.autostart? }
215 # clear pending watches
216 self.pending_watches.clear
221 # join the timer thread so we don't exit