god 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/History.txt +67 -1
  2. data/Manifest.txt +3 -4
  3. data/Rakefile +1 -1
  4. data/bin/god +19 -1
  5. data/lib/god.rb +86 -49
  6. data/lib/god/cli/command.rb +7 -1
  7. data/lib/god/cli/run.rb +58 -0
  8. data/lib/god/condition.rb +6 -2
  9. data/lib/god/conditions/cpu_usage.rb +7 -6
  10. data/lib/god/conditions/http_response_code.rb +5 -1
  11. data/lib/god/conditions/memory_usage.rb +7 -6
  12. data/lib/god/conditions/process_exits.rb +15 -10
  13. data/lib/god/conditions/process_running.rb +17 -13
  14. data/lib/god/diagnostics.rb +37 -0
  15. data/lib/god/driver.rb +108 -0
  16. data/lib/god/event_handler.rb +41 -1
  17. data/lib/god/logger.rb +69 -19
  18. data/lib/god/metric.rb +2 -2
  19. data/lib/god/process.rb +84 -27
  20. data/lib/god/task.rb +286 -29
  21. data/lib/god/timeline.rb +20 -31
  22. data/lib/god/watch.rb +26 -15
  23. data/test/configs/child_events/child_events.god +0 -5
  24. data/test/configs/child_polls/simple_server.rb +1 -1
  25. data/test/configs/daemon_events/simple_server_stop.rb +2 -0
  26. data/test/configs/stress/stress.god +1 -1
  27. data/test/configs/test.rb +12 -28
  28. data/test/test_condition.rb +8 -0
  29. data/test/test_conditions_http_response_code.rb +5 -5
  30. data/test/test_conditions_process_running.rb +6 -4
  31. data/test/test_driver.rb +11 -0
  32. data/test/test_event_handler.rb +7 -0
  33. data/test/test_god.rb +63 -62
  34. data/test/test_metric.rb +0 -16
  35. data/test/test_process.rb +29 -1
  36. data/test/test_task.rb +177 -1
  37. data/test/test_timeline.rb +2 -1
  38. data/test/test_watch.rb +24 -6
  39. metadata +6 -8
  40. data/lib/god/hub.rb +0 -222
  41. data/lib/god/timer.rb +0 -87
  42. data/test/test_hub.rb +0 -240
  43. data/test/test_timer.rb +0 -69
@@ -1,87 +0,0 @@
1
- module God
2
-
3
- class TimerEvent
4
- attr_accessor :condition, :at
5
-
6
- def initialize(condition, interval)
7
- self.condition = condition
8
- self.at = Time.now.to_i + interval
9
- end
10
- end
11
-
12
- class Timer
13
- INTERVAL = 0.25
14
-
15
- attr_reader :events, :timer
16
-
17
- @@timer = nil
18
-
19
- def self.get
20
- @@timer ||= Timer.new
21
- end
22
-
23
- def self.reset
24
- @@timer = nil
25
- end
26
-
27
- # Start the scheduler loop to handle events
28
- def initialize
29
- @events = []
30
- @mutex = Mutex.new
31
-
32
- @timer = Thread.new do
33
- loop do
34
- begin
35
- # get the current time
36
- t = Time.now.to_i
37
-
38
- # iterate over each event and trigger any that are due
39
- @events.each do |event|
40
- if t >= event.at
41
- self.trigger(event)
42
- @mutex.synchronize do
43
- @events.delete(event)
44
- end
45
- else
46
- break
47
- end
48
- end
49
-
50
- # sleep until next check
51
- sleep INTERVAL
52
- rescue Exception => e
53
- message = format("Unhandled exception (%s): %s\n%s",
54
- e.class, e.message, e.backtrace.join("\n"))
55
- applog(nil, :fatal, message)
56
- sleep INTERVAL
57
- end
58
- end
59
- end
60
- end
61
-
62
- # Create and register a new TimerEvent with the given parameters
63
- def schedule(condition, interval = condition.interval)
64
- @mutex.synchronize do
65
- @events << TimerEvent.new(condition, interval)
66
- @events.sort! { |x, y| x.at <=> y.at }
67
- end
68
- end
69
-
70
- # Remove any TimerEvents for the given condition
71
- def unschedule(condition)
72
- @mutex.synchronize do
73
- @events.reject! { |x| x.condition == condition }
74
- end
75
- end
76
-
77
- def trigger(event)
78
- Hub.trigger(event.condition)
79
- end
80
-
81
- # Join the timer thread
82
- def join
83
- @timer.join
84
- end
85
- end
86
-
87
- end
@@ -1,240 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class TestHub < Test::Unit::TestCase
4
- def setup
5
- God::Socket.stubs(:new).returns(true)
6
- God.reset
7
-
8
- God.watch do |w|
9
- w.name = 'foo'
10
- w.start = 'bar'
11
- w.interval = 10
12
- end
13
-
14
- @watch = God.watches['foo']
15
- end
16
-
17
- # attach
18
-
19
- def test_attach_should_store_condition_metric_association
20
- c = Conditions::FakePollCondition.new
21
- m = Metric.new(@watch, :foo)
22
- Hub.attach(c, m)
23
-
24
- assert_equal m, Hub.directory[c]
25
- end
26
-
27
- def test_attach_should_schedule_for_poll_condition
28
- c = Conditions::FakePollCondition.new
29
- m = Metric.new(@watch, :foo)
30
-
31
- Timer.any_instance.expects(:schedule).with(c, 0)
32
-
33
- Hub.attach(c, m)
34
- end
35
-
36
- def test_attach_should_regsiter_for_event_condition
37
- c = Conditions::FakeEventCondition.new
38
- m = Metric.new(@watch, :foo)
39
-
40
- c.expects(:register)
41
-
42
- Hub.attach(c, m)
43
- end
44
-
45
- # detach
46
-
47
- def test_detach_should_remove_condition_metric_association
48
- c = Conditions::FakePollCondition.new
49
- m = Metric.new(@watch, :foo)
50
-
51
- Hub.attach(c, m)
52
- Hub.detach(c)
53
-
54
- assert_nil Hub.directory[c]
55
- end
56
-
57
- def test_detach_should_unschedule_poll_conditions
58
- c = Conditions::FakePollCondition.new
59
- m = Metric.new(@watch, :foo)
60
- Hub.attach(c, m)
61
-
62
- Timer.any_instance.expects(:unschedule).with(c)
63
- c.expects(:deregister).never
64
-
65
- Hub.detach(c)
66
- end
67
-
68
- def test_detach_should_deregister_event_conditions
69
- c = Conditions::FakeEventCondition.new
70
- m = Metric.new(@watch, :foo)
71
- Hub.attach(c, m)
72
-
73
- c.expects(:deregister).once
74
-
75
- Hub.detach(c)
76
- end
77
-
78
- # trigger
79
-
80
- def test_trigger_should_handle_poll_for_poll_condition
81
- c = Conditions::FakePollCondition.new
82
- Hub.expects(:handle_poll).with(c)
83
-
84
- Hub.trigger(c)
85
- end
86
-
87
- def test_trigger_should_handle_event_for_event_condition
88
- c = Conditions::FakeEventCondition.new
89
- Hub.expects(:handle_event).with(c)
90
-
91
- Hub.trigger(c)
92
- end
93
-
94
- # handle_poll
95
-
96
- def test_handle_poll_no_change_should_reschedule
97
- c = Conditions::FakePollCondition.new
98
- c.interval = 10
99
-
100
- m = Metric.new(@watch, {true => :up})
101
- Hub.attach(c, m)
102
-
103
- c.expects(:test).returns(false)
104
- Timer.any_instance.expects(:schedule)
105
-
106
- no_stdout do
107
- t = Hub.handle_poll(c)
108
- t.join
109
- end
110
- end
111
-
112
- def test_handle_poll_change_should_move
113
- c = Conditions::FakePollCondition.new
114
- c.interval = 10
115
-
116
- m = Metric.new(@watch, {true => :up})
117
- Hub.attach(c, m)
118
-
119
- c.expects(:test).returns(true)
120
- @watch.expects(:move).with(:up)
121
-
122
- no_stdout do
123
- t = Hub.handle_poll(c)
124
- t.join
125
- end
126
- end
127
-
128
- def test_handle_poll_should_not_abort_on_exception
129
- c = Conditions::FakePollCondition.new
130
- c.interval = 10
131
-
132
- m = Metric.new(@watch, {true => :up})
133
- Hub.attach(c, m)
134
-
135
- c.expects(:test).raises(StandardError.new)
136
-
137
- assert_nothing_raised do
138
- no_stdout do
139
- t = Hub.handle_poll(c)
140
- t.join
141
- end
142
- end
143
- end
144
-
145
- def test_handle_poll_should_use_overridden_transition
146
- c = Conditions::Tries.new
147
- c.times = 1
148
- c.transition = :start
149
- c.prepare
150
-
151
- m = Metric.new(@watch, {true => :up})
152
- Hub.attach(c, m)
153
-
154
- @watch.expects(:move).with(:start)
155
-
156
- no_stdout do
157
- t = Hub.handle_poll(c)
158
- t.join
159
- end
160
- end
161
-
162
- def test_handle_poll_should_notify_if_triggering
163
- c = Conditions::FakePollCondition.new
164
- c.interval = 10
165
- c.notify = 'tom'
166
-
167
- m = Metric.new(@watch, {true => :up})
168
- Hub.attach(c, m)
169
-
170
- c.expects(:test).returns(true)
171
- Hub.expects(:notify)
172
-
173
- no_stdout do
174
- t = Hub.handle_poll(c)
175
- t.join
176
- end
177
- end
178
-
179
- def test_handle_poll_should_not_notify_if_not_triggering
180
- c = Conditions::FakePollCondition.new
181
- c.interval = 10
182
- c.notify = 'tom'
183
-
184
- m = Metric.new(@watch, {true => :up})
185
- Hub.attach(c, m)
186
-
187
- c.expects(:test).returns(false)
188
- Hub.expects(:notify).never
189
-
190
- no_stdout do
191
- t = Hub.handle_poll(c)
192
- t.join
193
- end
194
- end
195
-
196
- # handle_event
197
-
198
- def test_handle_event_should_move
199
- c = Conditions::FakeEventCondition.new
200
-
201
- m = Metric.new(@watch, {true => :up})
202
- Hub.attach(c, m)
203
-
204
- @watch.expects(:move).with(:up)
205
-
206
- no_stdout do
207
- t = Hub.handle_event(c)
208
- t.join
209
- end
210
- end
211
-
212
- def test_handle_event_should_notify_if_triggering
213
- c = Conditions::FakeEventCondition.new
214
- c.notify = 'tom'
215
-
216
- m = Metric.new(@watch, {true => :up})
217
- Hub.attach(c, m)
218
-
219
- Hub.expects(:notify)
220
-
221
- no_stdout do
222
- t = Hub.handle_event(c)
223
- t.join
224
- end
225
- end
226
-
227
- def test_handle_event_should_not_notify_if_no_notify_set
228
- c = Conditions::FakeEventCondition.new
229
-
230
- m = Metric.new(@watch, {true => :up})
231
- Hub.attach(c, m)
232
-
233
- Hub.expects(:notify).never
234
-
235
- no_stdout do
236
- t = Hub.handle_event(c)
237
- t.join
238
- end
239
- end
240
- end
@@ -1,69 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class TestTimer < Test::Unit::TestCase
4
- def setup
5
- Timer.reset
6
- @t = Timer.get
7
- end
8
-
9
- def test_new_timer_should_have_no_events
10
- assert_equal 0, @t.events.size
11
- end
12
-
13
- def test_schedule_should_queue_event
14
- Time.stubs(:now).returns(0)
15
-
16
- w = Watch.new
17
- @t.schedule(stub(:interval => 20))
18
-
19
- assert_equal 1, @t.events.size
20
- end
21
-
22
- def test_timer_should_remove_expired_events
23
- @t.schedule(stub(:interval => 0))
24
- sleep(0.3)
25
- assert_equal 0, @t.events.size
26
- end
27
-
28
- def test_timer_should_remove_only_expired_events
29
- @t.schedule(stub(:interval => 0))
30
- @t.schedule(stub(:interval => 1000))
31
- sleep(0.3)
32
- assert_equal 1, @t.events.size
33
- end
34
-
35
- def test_timer_should_sort_timer_events
36
- @t.schedule(stub(:interval => 1000))
37
- @t.schedule(stub(:interval => 800))
38
- @t.schedule(stub(:interval => 900))
39
- @t.schedule(stub(:interval => 100))
40
- sleep(0.3)
41
- assert_equal [100, 800, 900, 1000], @t.events.map { |x| x.condition.interval }
42
- end
43
-
44
- def test_unschedule_should_remove_conditions
45
- a = stub()
46
- b = stub()
47
- @t.schedule(a, 100)
48
- @t.schedule(b, 200)
49
- assert_equal 2, @t.events.size
50
- @t.unschedule(a)
51
- assert_equal 1, @t.events.size
52
- end
53
-
54
- def test_time_should_recover_from_exceptions
55
- @t.expects(:trigger).raises(Exception.new)
56
- no_stdout do
57
- @t.schedule(stub(:interval => 0))
58
- sleep(0.3)
59
- @t.schedule(stub(:interval => 0))
60
- end
61
- end
62
-
63
- # join
64
-
65
- def test_join_should_join
66
- Thread.any_instance.expects(:join)
67
- @t.join
68
- end
69
- end