daemonizer 0.4.18 → 0.5.0.beta.1
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.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/Rakefile +9 -29
- data/daemonizer.gemspec +20 -69
- data/lib/daemonizer.rb +10 -4
- data/lib/daemonizer/cli.rb +14 -1
- data/lib/daemonizer/config.rb +2 -2
- data/lib/daemonizer/dsl.rb +16 -4
- data/lib/daemonizer/engine.rb +41 -36
- data/lib/daemonizer/option.rb +11 -5
- data/lib/daemonizer/process_manager.rb +7 -3
- data/lib/daemonizer/version.rb +3 -0
- data/lib/daemonizer/worker.rb +16 -2
- data/lib/daemonizer/worker_pool.rb +10 -4
- data/spec/cli/debugging_spec.rb +45 -0
- data/spec/cli/not_started_spec.rb +127 -0
- data/spec/cli/started_spec.rb +121 -0
- data/spec/common/forking_spec.rb +35 -0
- data/spec/settings/callbacks_spec.rb +103 -0
- data/spec/settings/options_spec.rb +146 -0
- data/spec/settings/pools_spec.rb +43 -0
- data/spec/spec_helper.rb +56 -8
- data/spec/support/daemonfile_factory.rb +33 -0
- data/spec/support/helpers.rb +70 -0
- data/spec/support/path.rb +18 -0
- data/spec/support/processes.rb +23 -0
- data/spec/support/ruby_ext.rb +19 -0
- metadata +107 -50
- data/VERSION +0 -1
- data/spec/spec.opts +0 -1
- data/spec/test_spec.rb +0 -5
@@ -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
|
data/lib/daemonizer/worker.rb
CHANGED
@@ -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
|