daemonizer 0.4.18 → 0.5.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,13 +21,13 @@ module Daemonizer
21
21
  Daemonizer.logger.debug "Checking workers' health..."
22
22
  break if shutdown?
23
23
  @pool.check_workers
24
-
24
+
25
25
  @config.on_poll.each do |on_poll|
26
26
  on_poll.call(@pool)
27
27
  end
28
28
 
29
29
  break if shutdown?
30
- Daemonizer.logger.debug "Sleeping for #{@config.poll_period} seconds..."
30
+ Daemonizer.logger.debug "Sleeping for #{@config.poll_period} seconds..."
31
31
  sleep(@config.poll_period)
32
32
  end
33
33
  rescue Exception => e
@@ -69,7 +69,7 @@ module Daemonizer
69
69
  return false
70
70
  end
71
71
 
72
- def stop_workers(force = false)
72
+ def stop_workers(force = false)
73
73
  # Set shutdown flag
74
74
  Daemonizer.logger.debug "Stopping workers#{force ? ' (forced)' : ''}..."
75
75
 
@@ -77,6 +77,10 @@ module Daemonizer
77
77
  @pool.stop_workers(force)
78
78
  end
79
79
 
80
+ def send_signal_to_workers(signal)
81
+ @pool.send_signal_to_workers(signal)
82
+ end
83
+
80
84
  def shutdown?
81
85
  @shutdown
82
86
  end
@@ -0,0 +1,3 @@
1
+ module Daemonizer
2
+ VERSION = "0.5.0.beta.1"
3
+ end
@@ -28,11 +28,13 @@ module Daemonizer
28
28
  STDIN.reopen '/dev/null'
29
29
  STDOUT.reopen '/dev/null', 'a'
30
30
  STDERR.reopen STDOUT
31
-
31
+
32
+ setup_signals
33
+
32
34
  @pid = Process.pid
33
35
  Daemonizer.reopen_log_file
34
36
  Daemonizer.logger_context = "#{@pid}/#{@worker_id}"
35
-
37
+
36
38
  Daemonizer.logger.info "Log file reopened after fork"
37
39
  normal_exit = false
38
40
  begin
@@ -80,5 +82,17 @@ module Daemonizer
80
82
  Daemonizer.logger.error("Exception from kill: #{e} at #{e.backtrace.first}")
81
83
  end
82
84
  end
85
+
86
+ def send_signal(signal)
87
+ Process.kill(signal, @pid)
88
+ end
89
+
90
+ private
91
+
92
+ def setup_signals
93
+ trap('SIGHUP') do
94
+ Daemonizer.reopen_log_file
95
+ end
96
+ end
83
97
  end
84
98
  end
@@ -1,7 +1,7 @@
1
1
  module Daemonizer
2
2
  class WorkerPool
3
3
  MONITOR_VALUE = [:vm_size, :private_dirty_rss, :rss]
4
-
4
+
5
5
  attr_reader :name
6
6
  attr_reader :stats
7
7
 
@@ -12,7 +12,7 @@ module Daemonizer
12
12
  @workers = []
13
13
  @stats = ::SimpleStatistics::DataSet.new
14
14
  end
15
-
15
+
16
16
  def find_worker_by_name(name)
17
17
  @workers.detect do |w|
18
18
  w.process_name.to_s == name.to_s
@@ -29,7 +29,7 @@ module Daemonizer
29
29
  worker = Worker.new(name, @pm, i+1, &@worker_block)
30
30
  @workers << worker
31
31
  @stats.add_data(worker.process_name)
32
- Daemonizer.logger.info "Gathering data for #{worker.name}"
32
+ Daemonizer.logger.info "Gathering data for #{worker.name}"
33
33
  end
34
34
  rescue Exception => e
35
35
  Daemonizer.logger.info "Result - #{e.inspect}"
@@ -45,7 +45,7 @@ module Daemonizer
45
45
  @stats[worker_name][value].add_probe(p.send(value))
46
46
  end
47
47
  end
48
-
48
+
49
49
  @workers.each do |worker|
50
50
  unless worker.running? || worker.shutdown?
51
51
  Daemonizer.logger.warn "Worker #{worker.name} is not running. Restart!"
@@ -76,5 +76,11 @@ module Daemonizer
76
76
  worker.stop(force)
77
77
  end
78
78
  end
79
+
80
+ def send_signal_to_workers(signal)
81
+ @workers.each do |worker|
82
+ worker.send_signal(signal)
83
+ end
84
+ end
79
85
  end
80
86
  end
@@ -0,0 +1,45 @@
1
+ require "spec_helper"
2
+
3
+ describe "with Daemonfile and daemonzier is in 'debug' mode" do
4
+
5
+ before :each do
6
+ @pid_files = simple_daemonfile(
7
+ :name => :test1,
8
+ :pid_file =>"#{tmp_dir}/test1.pid",
9
+ :on_prepare => "Daemonizer.logger.info \"test1: executed prepare\"",
10
+ :on_start => "Daemonizer.logger.info \"test1: executed start\"")
11
+ end
12
+
13
+ describe "with all pools" do
14
+
15
+ before(:each) do
16
+ daemonizer :debug
17
+ end
18
+
19
+ it "should return valid text" do
20
+ @out.should match(/You should supply pool_name to debug/)
21
+ end
22
+
23
+ it "should not return anything to stderr" do
24
+ @err.should == ''
25
+ end
26
+ end
27
+
28
+ describe "with specific pool" do
29
+
30
+ before(:each) do
31
+ daemonizer "debug test1"
32
+ end
33
+
34
+ it "should return valid text" do
35
+ @out.should match(/test1: executed prepare/)
36
+ @out.should match(/test1: executed start/)
37
+ end
38
+
39
+ it "should not return anything to stderr" do
40
+ @err.should == ''
41
+ end
42
+ end
43
+
44
+
45
+ end
@@ -0,0 +1,127 @@
1
+ require "spec_helper"
2
+
3
+ describe "with Daemonfile and daemonzier is not started " do
4
+
5
+ before :each do
6
+ @pid_files = simple_daemonfile({:name => :test1, :pid_file =>"#{tmp_dir}/test1.pid"}, {:name => :test2, :pid_file => "#{tmp_dir}/test2.pid"})
7
+ end
8
+
9
+ describe "on call 'stats'" do
10
+ before(:each) do
11
+ daemonizer :stats
12
+ end
13
+
14
+ it "should return valid text" do
15
+ @out.should match(/It seems like pool 'test1' is not running/)
16
+ @out.should match(/It seems like pool 'test2' is not running/)
17
+ end
18
+
19
+ it "should not return anything to stderr" do
20
+ @err.should == ''
21
+ end
22
+ end
23
+
24
+ describe "on call 'logrotate'" do
25
+ before(:each) do
26
+ daemonizer :logrotate
27
+ end
28
+
29
+ it "should return valid text" do
30
+ @out.should match(/test1: not started/)
31
+ @out.should match(/test2: not started/)
32
+ end
33
+
34
+ it "should not return anything to stderr" do
35
+ @err.should == ''
36
+ end
37
+ end
38
+
39
+ describe "on call 'start'" do
40
+ describe "with all pools" do
41
+ before(:each) do
42
+ daemonizer :start
43
+ end
44
+
45
+ after(:each) do
46
+ daemonizer :stop
47
+ end
48
+
49
+ it "should print info about starting 2 pools" do
50
+ @out.should match(/test1: Starting pool/)
51
+ @out.should match(/test1: successfully started/)
52
+ @out.should match(/test2: Starting pool/)
53
+ @out.should match(/test2: successfully started/)
54
+ end
55
+
56
+ it "should not return anything to stderr" do
57
+ @err.should == ''
58
+ end
59
+
60
+ it "should run daemonizer processes" do
61
+ daemonizer_runned?(@pid_files[0]).should be_true
62
+ daemonizer_runned?(@pid_files[1]).should be_true
63
+ end
64
+ end
65
+
66
+ describe "with specific pool" do
67
+ before(:each) do
68
+ daemonizer "start test1"
69
+ end
70
+
71
+ after(:each) do
72
+ daemonizer "stop test1"
73
+ end
74
+
75
+ it "should print info about starting 2 pools" do
76
+ @out.should match(/test1: Starting pool/)
77
+ @out.should match(/test1: successfully started/)
78
+ @out.should_not match(/test2: Starting pool/)
79
+ @out.should_not match(/test2: successfully started/)
80
+ end
81
+
82
+ it "should not return anything to stderr" do
83
+ @err.should == ''
84
+ end
85
+
86
+ it "should run daemonizer processes" do
87
+ daemonizer_runned?(@pid_files[0]).should be_true
88
+ daemonizer_runned?(@pid_files[1]).should be_false
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "on call 'stop'" do
94
+ describe "with all pools" do
95
+
96
+ before(:each) do
97
+ daemonizer :stop
98
+ end
99
+
100
+ it "should return valid text" do
101
+ @out.should match(/test1: No pid file or a stale pid file!/)
102
+ @out.should match(/test2: No pid file or a stale pid file!/)
103
+ end
104
+
105
+ it "should not return anything to stderr" do
106
+ @err.should == ''
107
+ end
108
+ end
109
+
110
+ describe "with specific pool" do
111
+
112
+ before(:each) do
113
+ daemonizer "stop test1"
114
+ end
115
+
116
+ it "should return valid text" do
117
+ @out.should match(/test1: No pid file or a stale pid file!/)
118
+ @out.should_not match(/test2: No pid file or a stale pid file!/)
119
+ end
120
+
121
+ it "should not return anything to stderr" do
122
+ @err.should == ''
123
+ end
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+
3
+ describe "with Daemonfile and daemonzier is already started " do
4
+
5
+ before :each do
6
+ @pid_files = simple_daemonfile({:name => :test1, :pid_file =>"#{tmp_dir}/test1.pid"}, {:name => :test2, :pid_file => "#{tmp_dir}/test2.pid"})
7
+ daemonizer "start"
8
+ end
9
+
10
+ after :each do
11
+ daemonizer "stop"
12
+ end
13
+
14
+ describe "on call 'stats'" do
15
+ before(:each) do
16
+ daemonizer :stats
17
+ end
18
+
19
+ it "should return valid text" do
20
+ @out.should match(/test1 processes/)
21
+ @out.should match(/test2 processes/)
22
+ end
23
+
24
+ it "should not return anything to stderr" do
25
+ @err.should == ''
26
+ end
27
+ end
28
+
29
+ describe "on call 'logrotate'" do
30
+ before(:each) do
31
+ daemonizer :logrotate
32
+ end
33
+
34
+ it "should return valid text" do
35
+ @out.should match(/test1: log file reopened/)
36
+ @out.should match(/test2: log file reopened/)
37
+ end
38
+
39
+ it "should not return anything to stderr" do
40
+ @err.should == ''
41
+ end
42
+ end
43
+
44
+ describe "on call 'start'" do
45
+ describe "with all pools" do
46
+ before(:each) do
47
+ daemonizer 'start'
48
+ end
49
+
50
+ it "should print info about starting 2 pools" do
51
+ @out.should match(/test1: Can't start, another process exists!/)
52
+ @out.should match(/test2: Can't start, another process exists!/)
53
+ end
54
+
55
+ it "should not return anything to stderr" do
56
+ @err.should == ''
57
+ end
58
+
59
+ it "should run daemonizer processes" do
60
+ daemonizer_runned?(@pid_files[0]).should be_true
61
+ daemonizer_runned?(@pid_files[1]).should be_true
62
+ end
63
+ end
64
+
65
+ describe "with specific pool" do
66
+ before(:each) do
67
+ daemonizer "start test1"
68
+ end
69
+
70
+ it "should print info about starting 2 pools" do
71
+ @out.should match(/test1: Can't start, another process exists!/)
72
+ @out.should_not match(/test2/)
73
+ end
74
+
75
+ it "should not return anything to stderr" do
76
+ @err.should == ''
77
+ end
78
+
79
+ it "should run daemonizer processes" do
80
+ daemonizer_runned?(@pid_files[0]).should be_true
81
+ daemonizer_runned?(@pid_files[1]).should be_true
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ describe "on call 'stop'" do
88
+ describe "with all pools" do
89
+
90
+ before(:each) do
91
+ daemonizer "stop"
92
+ end
93
+
94
+ it "should return valid text" do
95
+ @out.should match(/test1: Killing the process/)
96
+ @out.should match(/test2: Killing the process/)
97
+ end
98
+
99
+ it "should not return anything to stderr" do
100
+ @err.should == ''
101
+ end
102
+ end
103
+
104
+ describe "with specific pool" do
105
+
106
+ before(:each) do
107
+ daemonizer "stop test1"
108
+ end
109
+
110
+ it "should return valid text" do
111
+ @out.should match(/test1: Killing the process/)
112
+ @out.should_not match(/test2: Killing the process/)
113
+ end
114
+
115
+ it "should not return anything to stderr" do
116
+ @err.should == ''
117
+ end
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ describe "daemonzier after start" do
4
+
5
+ before :each do
6
+ @pid_files = simple_daemonfile(
7
+ :name => :test1,
8
+ :pid_file =>"#{tmp_dir}/test1.pid",
9
+ :on_start => "loop { sleep 1 }",
10
+ :workers => 3,
11
+ :poll_period => 1)
12
+ daemonizer :start
13
+ sleep 8
14
+ end
15
+
16
+ after :each do
17
+ daemonizer :stop
18
+ end
19
+
20
+ it "should create 3 forks" do
21
+ children_count(pid(@pid_files[0])).should == 3
22
+ end
23
+
24
+ describe "after one worker died" do
25
+ before :each do
26
+ Process.kill("KILL", children_pids(pid(@pid_files[0])).first.to_i)
27
+ sleep 5
28
+ end
29
+
30
+ it "should restore it" do
31
+ children_count(pid(@pid_files[0])).should == 3
32
+ end
33
+ end
34
+
35
+ end