rescue event register and implement transition state override
[god.git] / lib / god.rb
blobcbb0a170d23c4dc500c90fc02e3cd4bed979d022
1 $:.unshift File.dirname(__FILE__)     # For use/testing when no gem is installed
3 require 'syslog'
5 # internal requires
6 require 'god/errors'
8 require 'god/system/process'
10 require 'god/behavior'
11 require 'god/behaviors/clean_pid_file'
13 require 'god/condition'
14 require 'god/conditions/timeline'
15 require 'god/conditions/process_running'
16 require 'god/conditions/process_exits'
17 require 'god/conditions/tries'
18 require 'god/conditions/memory_usage'
19 require 'god/conditions/cpu_usage'
20 require 'god/conditions/always'
22 require 'god/reporter'
23 require 'god/server'
24 require 'god/timer'
25 require 'god/hub'
27 require 'god/metric'
28 require 'god/watch'
30 require 'god/event_handler'
31 require 'god/registry'
32 require 'god/process'
34 require 'god/sugar'
36 $:.unshift File.join(File.dirname(__FILE__), *%w[.. ext god])
38 begin
39   Syslog.open('god')
40 rescue RuntimeError
41   Syslog.reopen('god')
42 end
44 God::EventHandler.load
46 module God
47   VERSION = '0.3.0'
48   
49   class << self
50     attr_accessor :inited, :host, :port
51     
52     # drb
53     attr_accessor :server
54     
55     # api
56     attr_accessor :watches, :groups
57   end
58   
59   def self.init
60     # only do this once
61     return if self.inited
62     
63     # variable init
64     self.watches = {}
65     self.groups = {}
66     
67     # yield to the config file
68     yield self if block_given?
69     
70     # instantiate server
71     self.server = Server.new(self.host, self.port)
72     
73     # init has been executed
74     self.inited = true
75   end
76     
77   # Where pid files created by god will go by default
78   def self.pid_file_directory
79     @pid_file_directory ||= '/var/run/god'
80   end
81   
82   def self.pid_file_directory=(value)
83     @pid_file_directory = value
84   end
85   
86   # Instantiate a new, empty Watch object and pass it to the mandatory
87   # block. The attributes of the watch will be set by the configuration
88   # file.
89   def self.watch
90     self.init
91     
92     w = Watch.new
93     yield(w)
94     
95     # ensure the new watch has a unique name
96     if self.watches[w.name] || self.groups[w.name]
97       abort "Watch name '#{w.name}' already used for a Watch or Group"
98     end
99     
100     # add to list of watches
101     self.watches[w.name] = w
102     
103     # add to group if specified
104     if w.group
105       # ensure group name hasn't been used for a watch already
106       if self.watches[w.group]
107         abort "Group name '#{w.group}' already used for a Watch"
108       end
109     
110       self.groups[w.group] ||= []
111       self.groups[w.group] << w
112     end
114     # register watch
115     w.register!
116   end
117   
118   def self.control(name, command)
119     # get the list of watches
120     watches = Array(self.watches[name] || self.groups[name])
121   
122     # do the command
123     case command
124       when "start", "monitor"
125         watches.each { |w| w.monitor }
126       when "restart"
127         watches.each { |w| w.move(:restart) }
128       when "stop"
129         watches.each { |w| w.unmonitor.action(:stop) }
130       when "unmonitor"
131         watches.each { |w| w.unmonitor }
132       else
133         raise InvalidCommandError.new
134     end
135     
136     watches
137   end
138     
139   def self.start
140     # make sure there's something to do
141     if self.watches.nil? || self.watches.empty?
142       abort "You must specify at least one watch!"
143     end
144     
145     # start event handler system
146     EventHandler.start if EventHandler.loaded?
147     
148     # start the timer system
149     Timer.get
151     # start monitoring any watches set to autostart
152     self.watches.values.each { |w| w.monitor if w.autostart? }
153     
154     # join the timer thread so we don't exit
155     Timer.get.join
156   end
157   
158   def self.at_exit
159     self.start
160   end
161   
162   def self.load(glob)
163     Dir[glob].each do |f|
164       Kernel.load f
165     end
166   end
169 at_exit do
170   God.at_exit