daemonizer 0.4.12 → 0.4.13
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/Rakefile +23 -9
- data/VERSION +1 -1
- data/daemonizer.gemspec +19 -3
- data/lib/daemonizer.rb +1 -0
- data/lib/daemonizer/cli.rb +4 -1
- data/lib/daemonizer/config.rb +2 -1
- data/lib/daemonizer/dsl.rb +7 -0
- data/lib/daemonizer/handler.rb +2 -5
- data/lib/daemonizer/process_manager.rb +13 -15
- data/lib/daemonizer/stats.rb +1 -0
- data/lib/daemonizer/worker.rb +3 -1
- data/lib/daemonizer/worker_pool.rb +34 -4
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/test_spec.rb +5 -0
- metadata +54 -6
data/Rakefile
CHANGED
@@ -11,22 +11,36 @@ begin
|
|
11
11
|
gemspec.homepage = "http://github.com/glebpom/daemonizer"
|
12
12
|
gemspec.authors = ["Gleb Pomykalov"]
|
13
13
|
gemspec.add_dependency('thor', '>= 0.13.7')
|
14
|
+
gemspec.add_dependency('simple-statistics', '>= 0')
|
15
|
+
gemspec.add_development_dependency "rspec", ">= 1.2.9"
|
16
|
+
gemspec.add_development_dependency "yard", ">= 0"
|
14
17
|
end
|
15
18
|
Jeweler::GemcutterTasks.new
|
16
19
|
rescue LoadError
|
17
20
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
18
21
|
end
|
19
22
|
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :spec => :check_dependencies
|
36
|
+
|
37
|
+
task :default => :spec
|
38
|
+
|
20
39
|
begin
|
21
40
|
require 'yard'
|
22
|
-
YARD::Rake::YardocTask.new
|
23
|
-
t.options = ['--title', 'Daemonizer Documentation']
|
24
|
-
if ENV['PRIVATE']
|
25
|
-
t.options.concat ['--protected', '--private']
|
26
|
-
else
|
27
|
-
t.options.concat ['--protected', '--no-private']
|
28
|
-
end
|
29
|
-
end
|
41
|
+
YARD::Rake::YardocTask.new
|
30
42
|
rescue LoadError
|
31
|
-
|
43
|
+
task :yardoc do
|
44
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
45
|
+
end
|
32
46
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.13
|
data/daemonizer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{daemonizer}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.13"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Gleb Pomykalov"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-08-04}
|
13
13
|
s.default_executable = %q{daemonizer}
|
14
14
|
s.description = %q{Inspired by bundler and rack. Mostly built on top of Alexey Kovyrin's loops code. http://github.com/kovyrin/loops}
|
15
15
|
s.email = %q{glebpom@gmail.com}
|
@@ -39,13 +39,20 @@ Gem::Specification.new do |s|
|
|
39
39
|
"lib/daemonizer/process_manager.rb",
|
40
40
|
"lib/daemonizer/stats.rb",
|
41
41
|
"lib/daemonizer/worker.rb",
|
42
|
-
"lib/daemonizer/worker_pool.rb"
|
42
|
+
"lib/daemonizer/worker_pool.rb",
|
43
|
+
"spec/spec.opts",
|
44
|
+
"spec/spec_helper.rb",
|
45
|
+
"spec/test_spec.rb"
|
43
46
|
]
|
44
47
|
s.homepage = %q{http://github.com/glebpom/daemonizer}
|
45
48
|
s.rdoc_options = ["--charset=UTF-8"]
|
46
49
|
s.require_paths = ["lib"]
|
47
50
|
s.rubygems_version = %q{1.3.7}
|
48
51
|
s.summary = %q{Daemonizer allows you to easily create custom daemons on ruby. Supporting prefork model}
|
52
|
+
s.test_files = [
|
53
|
+
"spec/spec_helper.rb",
|
54
|
+
"spec/test_spec.rb"
|
55
|
+
]
|
49
56
|
|
50
57
|
if s.respond_to? :specification_version then
|
51
58
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -53,11 +60,20 @@ Gem::Specification.new do |s|
|
|
53
60
|
|
54
61
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
62
|
s.add_runtime_dependency(%q<thor>, [">= 0.13.7"])
|
63
|
+
s.add_runtime_dependency(%q<simple-statistics>, [">= 0"])
|
64
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
65
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
56
66
|
else
|
57
67
|
s.add_dependency(%q<thor>, [">= 0.13.7"])
|
68
|
+
s.add_dependency(%q<simple-statistics>, [">= 0"])
|
69
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
70
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
58
71
|
end
|
59
72
|
else
|
60
73
|
s.add_dependency(%q<thor>, [">= 0.13.7"])
|
74
|
+
s.add_dependency(%q<simple-statistics>, [">= 0"])
|
75
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
76
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
61
77
|
end
|
62
78
|
end
|
63
79
|
|
data/lib/daemonizer.rb
CHANGED
data/lib/daemonizer/cli.rb
CHANGED
@@ -85,7 +85,10 @@ module Daemonizer
|
|
85
85
|
|
86
86
|
desc "debug", "Debug pool (do not demonize)"
|
87
87
|
def debug(pool_name = nil)
|
88
|
-
|
88
|
+
if pool_name.nil?
|
89
|
+
puts "You should supply pool_name to debug"
|
90
|
+
exit 1
|
91
|
+
end
|
89
92
|
control_pools_loop(pool_name, "execution ended", true) do |pool|
|
90
93
|
STDOUT.sync = true
|
91
94
|
|
data/lib/daemonizer/config.rb
CHANGED
@@ -32,6 +32,7 @@ module Daemonizer
|
|
32
32
|
@options[:handler] ||= nil
|
33
33
|
@options[:handler_options] ||= {}
|
34
34
|
@options[:callbacks] ||= {}
|
35
|
+
@options[:on_poll] ||= []
|
35
36
|
@options[:cow_friendly] = true if @options[:cow_friendly].nil?
|
36
37
|
end
|
37
38
|
|
@@ -70,7 +71,7 @@ module Daemonizer
|
|
70
71
|
validate_file(self.pid_file)
|
71
72
|
end
|
72
73
|
|
73
|
-
[:workers, :poll_period, :root, :cow_friendly, :callbacks, :handler_options].each do |method|
|
74
|
+
[:workers, :poll_period, :root, :cow_friendly, :callbacks, :handler_options, :on_poll].each do |method|
|
74
75
|
define_method method do
|
75
76
|
@options[method.to_sym]
|
76
77
|
end
|
data/lib/daemonizer/dsl.rb
CHANGED
@@ -39,6 +39,12 @@ class Daemonizer::Dsl
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
def on_poll(&block)
|
43
|
+
@options[:on_poll] ||= []
|
44
|
+
@options[:on_poll] << block
|
45
|
+
end
|
46
|
+
|
47
|
+
|
42
48
|
def not_cow_friendly
|
43
49
|
@options[:cow_friendly] = false
|
44
50
|
end
|
@@ -94,6 +100,7 @@ class Daemonizer::Dsl
|
|
94
100
|
options = @options.dup
|
95
101
|
options[:handler_options] = @options[:handler_options].dup if @options[:handler_options]
|
96
102
|
options[:callbacks] = @options[:callbacks].dup if @options[:callbacks]
|
103
|
+
options[:on_poll] = @options[:on_poll].dup if @options[:on_poll]
|
97
104
|
options
|
98
105
|
end
|
99
106
|
end
|
data/lib/daemonizer/handler.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Daemonizer
|
2
2
|
class ProcessManager
|
3
3
|
def initialize(config)
|
4
|
-
@worker_pools = {}
|
5
4
|
@shutdown = false
|
6
5
|
@config = config
|
7
6
|
end
|
@@ -10,8 +9,8 @@ module Daemonizer
|
|
10
9
|
def start_workers(&blk)
|
11
10
|
raise ArgumentError, "Need a worker block!" unless block_given?
|
12
11
|
Daemonizer.logger.info "starting all workers"
|
13
|
-
@
|
14
|
-
@
|
12
|
+
@pool = WorkerPool.new(@config.pool, self, &blk)
|
13
|
+
@pool.start_workers(@config.workers)
|
15
14
|
end
|
16
15
|
|
17
16
|
def monitor_workers
|
@@ -20,15 +19,20 @@ module Daemonizer
|
|
20
19
|
Daemonizer.logger.debug 'Starting workers monitoring code...'
|
21
20
|
loop do
|
22
21
|
Daemonizer.logger.debug "Checking workers' health..."
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
break if shutdown?
|
23
|
+
@pool.check_workers
|
24
|
+
|
25
|
+
@config.on_poll.each do |on_poll|
|
26
|
+
on_poll.call(@pool)
|
26
27
|
end
|
27
28
|
|
28
29
|
break if shutdown?
|
29
30
|
Daemonizer.logger.debug "Sleeping for #{@config.poll_period} seconds..."
|
30
31
|
sleep(@config.poll_period)
|
31
32
|
end
|
33
|
+
rescue Exception => e
|
34
|
+
Daemonizer.logger.fatal "Monitor error: #{e.to_s}\n #{e.backtrace.join("\n ")}"
|
35
|
+
raise
|
32
36
|
ensure
|
33
37
|
Daemonizer.logger.debug "Workers monitoring loop is finished, starting shutdown..."
|
34
38
|
# Send out stop signals
|
@@ -51,11 +55,7 @@ module Daemonizer
|
|
51
55
|
def wait_for_workers(seconds)
|
52
56
|
seconds.times do
|
53
57
|
Daemonizer.logger.debug "Shutting down... waiting for workers to die (we have #{seconds} seconds)..."
|
54
|
-
running_total =
|
55
|
-
|
56
|
-
@worker_pools.each do |name, pool|
|
57
|
-
running_total += pool.wait_workers
|
58
|
-
end
|
58
|
+
running_total = @pool.wait_workers
|
59
59
|
|
60
60
|
if running_total.zero?
|
61
61
|
Daemonizer.logger.debug "All workers are dead. Exiting..."
|
@@ -69,14 +69,12 @@ 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
|
|
76
76
|
# Termination loop
|
77
|
-
@
|
78
|
-
pool.stop_workers(force)
|
79
|
-
end
|
77
|
+
@pool.stop_workers(force)
|
80
78
|
end
|
81
79
|
|
82
80
|
def shutdown?
|
data/lib/daemonizer/stats.rb
CHANGED
data/lib/daemonizer/worker.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Daemonizer
|
2
2
|
class Worker
|
3
3
|
attr_reader :name
|
4
|
+
attr_reader :process_name
|
4
5
|
attr_reader :pid
|
5
6
|
|
6
7
|
def initialize(name, pm, worker_id, &blk)
|
@@ -10,6 +11,7 @@ module Daemonizer
|
|
10
11
|
@pm = pm
|
11
12
|
@worker_block = blk
|
12
13
|
@worker_id = worker_id
|
14
|
+
@process_name = "#{@name} worker: instance #{@worker_id}"
|
13
15
|
end
|
14
16
|
|
15
17
|
def shutdown?
|
@@ -34,7 +36,7 @@ module Daemonizer
|
|
34
36
|
Daemonizer.logger.info "Log file reopened after fork"
|
35
37
|
normal_exit = false
|
36
38
|
begin
|
37
|
-
$0 = "#{@
|
39
|
+
$0 = "#{@process_name}\0"
|
38
40
|
@worker_block.call(@worker_id)
|
39
41
|
normal_exit = true
|
40
42
|
exit(0)
|
@@ -1,12 +1,22 @@
|
|
1
1
|
module Daemonizer
|
2
2
|
class WorkerPool
|
3
|
+
MONITOR_VALUE = [:vm_size, :private_dirty_rss, :rss]
|
4
|
+
|
3
5
|
attr_reader :name
|
6
|
+
attr_reader :stats
|
4
7
|
|
5
8
|
def initialize(name, pm, &blk)
|
6
9
|
@name = name
|
7
10
|
@pm = pm
|
8
11
|
@worker_block = blk
|
9
12
|
@workers = []
|
13
|
+
@stats = ::SimpleStatistics::DataSet.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_worker_by_name(name)
|
17
|
+
@workers.detect do |w|
|
18
|
+
w.process_name.to_s == name.to_s
|
19
|
+
end
|
10
20
|
end
|
11
21
|
|
12
22
|
def shutdown?
|
@@ -16,19 +26,39 @@ module Daemonizer
|
|
16
26
|
def start_workers(number)
|
17
27
|
Daemonizer.logger.debug "Creating #{number} workers for #{name} pool..."
|
18
28
|
number.times do |i|
|
19
|
-
|
29
|
+
worker = Worker.new(name, @pm, i+1, &@worker_block)
|
30
|
+
@workers << worker
|
31
|
+
@stats.add_data(worker.process_name)
|
32
|
+
Daemonizer.logger.info "Gathering data for #{worker.name}"
|
20
33
|
end
|
34
|
+
rescue Exception => e
|
35
|
+
Daemonizer.logger.info "Result - #{e.inspect}"
|
21
36
|
end
|
22
37
|
|
23
38
|
def check_workers
|
24
39
|
Daemonizer.logger.debug "Checking loop #{name} workers..."
|
40
|
+
|
41
|
+
Daemonizer::Stats::MemoryStats.new(self).find_workers.each do |p|
|
42
|
+
worker_name = p.name
|
43
|
+
MONITOR_VALUE.each do |value|
|
44
|
+
@stats.tick(value)
|
45
|
+
@stats[worker_name][value].add_probe(p.send(value))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
25
49
|
@workers.each do |worker|
|
26
|
-
|
27
|
-
|
28
|
-
|
50
|
+
unless worker.running? || worker.shutdown?
|
51
|
+
Daemonizer.logger.warn "Worker #{worker.name} is not running. Restart!"
|
52
|
+
@stats.add_data(worker.process_name)
|
53
|
+
MONITOR_VALUE.each do |v|
|
54
|
+
@stats[worker.process_name].reset(v)
|
55
|
+
end
|
56
|
+
worker.run
|
57
|
+
end
|
29
58
|
end
|
30
59
|
end
|
31
60
|
|
61
|
+
|
32
62
|
def wait_workers
|
33
63
|
running = 0
|
34
64
|
@workers.each do |worker|
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
data/spec/test_spec.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: daemonizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 13
|
10
|
+
version: 0.4.13
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Gleb Pomykalov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-08-04 00:00:00 +04:00
|
19
19
|
default_executable: daemonizer
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -34,6 +34,50 @@ dependencies:
|
|
34
34
|
version: 0.13.7
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: simple-statistics
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: rspec
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 13
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 2
|
63
|
+
- 9
|
64
|
+
version: 1.2.9
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: yard
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
37
81
|
description: Inspired by bundler and rack. Mostly built on top of Alexey Kovyrin's loops code. http://github.com/kovyrin/loops
|
38
82
|
email: glebpom@gmail.com
|
39
83
|
executables:
|
@@ -65,6 +109,9 @@ files:
|
|
65
109
|
- lib/daemonizer/stats.rb
|
66
110
|
- lib/daemonizer/worker.rb
|
67
111
|
- lib/daemonizer/worker_pool.rb
|
112
|
+
- spec/spec.opts
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
- spec/test_spec.rb
|
68
115
|
has_rdoc: true
|
69
116
|
homepage: http://github.com/glebpom/daemonizer
|
70
117
|
licenses: []
|
@@ -99,5 +146,6 @@ rubygems_version: 1.3.7
|
|
99
146
|
signing_key:
|
100
147
|
specification_version: 3
|
101
148
|
summary: Daemonizer allows you to easily create custom daemons on ruby. Supporting prefork model
|
102
|
-
test_files:
|
103
|
-
|
149
|
+
test_files:
|
150
|
+
- spec/spec_helper.rb
|
151
|
+
- spec/test_spec.rb
|