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.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage
6
+ tmp
7
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in daemonizer.gemspec
4
+ gemspec
data/Rakefile CHANGED
@@ -1,35 +1,15 @@
1
- require 'rubygems'
2
- require 'rubygems/specification'
1
+ require "bundler/gem_tasks"
3
2
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gemspec|
7
- gemspec.name = "daemonizer"
8
- gemspec.summary = "Daemonizer allows you to easily create custom daemons on ruby. Supporting prefork model"
9
- gemspec.description = "Inspired by bundler and rack. Mostly built on top of Alexey Kovyrin's loops code. http://github.com/kovyrin/loops"
10
- gemspec.email = "glebpom@gmail.com"
11
- gemspec.homepage = "http://github.com/glebpom/daemonizer"
12
- gemspec.authors = ["Gleb Pomykalov"]
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"
17
- end
18
- Jeweler::GemcutterTasks.new
19
- rescue LoadError
20
- puts "Jeweler not available. Install it with: gem install jeweler"
21
- end
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']
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new do |t|
5
+ t.rspec_opts = %w(-fs --color)
6
+ t.ruby_opts = %w(-w)
27
7
  end
28
8
 
29
- Spec::Rake::SpecTask.new(:rcov) do |spec|
30
- spec.libs << 'lib' << 'spec'
31
- spec.pattern = 'spec/**/*_spec.rb'
32
- spec.rcov = true
9
+ desc "Run all specs with rcov"
10
+ RSpec::Core::RakeTask.new(:rcov => :spec) do |t|
11
+ t.rcov = true
12
+ t.rcov_opts = %w{--exclude gems\/,spec\/}
33
13
  end
34
14
 
35
15
  task :spec => :check_dependencies
data/daemonizer.gemspec CHANGED
@@ -1,77 +1,28 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "daemonizer/version"
5
4
 
6
5
  Gem::Specification.new do |s|
7
- s.name = %q{daemonizer}
8
- s.version = "0.4.18"
6
+ s.name = "daemonizer"
7
+ s.version = Daemonizer::VERSION
8
+ s.authors = ["Gleb Pomykalov"]
9
+ s.email = ["glebpom@gmail.com"]
10
+ s.homepage = "http://github.com/glebpom/daemonizer"
11
+ s.summary = "Daemonizer allows you to easily create custom daemons on ruby. Supporting prefork model"
12
+ s.description = "Inspired by bundler and rack. Mostly built on top of Alexey Kovyrin's loops code. http://github.com/kovyrin/loops"
9
13
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Gleb Pomykalov"]
12
- s.date = %q{2011-10-04}
13
- s.default_executable = %q{daemonizer}
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
- s.email = %q{glebpom@gmail.com}
16
- s.executables = ["daemonizer"]
17
- s.extra_rdoc_files = [
18
- "LICENSE",
19
- "README.md"
20
- ]
21
- s.files = [
22
- "LICENSE",
23
- "README.md",
24
- "ROADMAP",
25
- "Rakefile",
26
- "VERSION",
27
- "bin/daemonizer",
28
- "daemonizer.gemspec",
29
- "lib/daemonizer.rb",
30
- "lib/daemonizer/autoload.rb",
31
- "lib/daemonizer/cli.rb",
32
- "lib/daemonizer/config.rb",
33
- "lib/daemonizer/daemonize.rb",
34
- "lib/daemonizer/dsl.rb",
35
- "lib/daemonizer/engine.rb",
36
- "lib/daemonizer/errors.rb",
37
- "lib/daemonizer/handler.rb",
38
- "lib/daemonizer/option.rb",
39
- "lib/daemonizer/process_manager.rb",
40
- "lib/daemonizer/stats.rb",
41
- "lib/daemonizer/worker.rb",
42
- "lib/daemonizer/worker_pool.rb",
43
- "spec/spec.opts",
44
- "spec/spec_helper.rb",
45
- "spec/test_spec.rb"
46
- ]
47
- s.homepage = %q{http://github.com/glebpom/daemonizer}
14
+ s.rubyforge_project = "daemonizer"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
48
19
  s.require_paths = ["lib"]
49
- s.rubygems_version = %q{1.5.3}
50
- s.summary = %q{Daemonizer allows you to easily create custom daemons on ruby. Supporting prefork model}
51
- s.test_files = [
52
- "spec/spec_helper.rb",
53
- "spec/test_spec.rb"
54
- ]
55
20
 
56
- if s.respond_to? :specification_version then
57
- s.specification_version = 3
21
+ s.add_development_dependency "rspec", ">=2.1.0"
22
+ s.add_development_dependency "mocha", ">=0.9.9"
23
+ s.add_development_dependency "yard", ">= 0"
24
+ s.add_development_dependency "rake"
58
25
 
59
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
- s.add_runtime_dependency(%q<thor>, [">= 0.13.7"])
61
- s.add_runtime_dependency(%q<simple-statistics>, [">= 0"])
62
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
63
- s.add_development_dependency(%q<yard>, [">= 0"])
64
- else
65
- s.add_dependency(%q<thor>, [">= 0.13.7"])
66
- s.add_dependency(%q<simple-statistics>, [">= 0"])
67
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
68
- s.add_dependency(%q<yard>, [">= 0"])
69
- end
70
- else
71
- s.add_dependency(%q<thor>, [">= 0.13.7"])
72
- s.add_dependency(%q<simple-statistics>, [">= 0"])
73
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
74
- s.add_dependency(%q<yard>, [">= 0"])
75
- end
26
+ s.add_runtime_dependency "thor", ">= 0.13.7"
27
+ s.add_runtime_dependency "simple-statistics", ">=0.0.3"
76
28
  end
77
-
data/lib/daemonizer.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'daemonizer/version'
1
2
  require 'rubygems'
2
3
  require 'yaml'
3
4
  require 'erb'
@@ -5,7 +6,6 @@ require 'pathname'
5
6
  require 'logger'
6
7
  require 'simple-statistics'
7
8
 
8
-
9
9
  module Daemonizer
10
10
 
11
11
  def self.root=(value)
@@ -59,7 +59,7 @@ module Daemonizer
59
59
  @@log_level ||= :info
60
60
  end
61
61
 
62
- def self.init_logger(name, log_file)
62
+ def self.init_logger(log_file)
63
63
  @@logger_file = File.open(log_file, File::WRONLY | File::APPEND)
64
64
  @@logger_file.sync = true
65
65
  @@logger = Logger.new(@@logger_file)
@@ -74,7 +74,13 @@ module Daemonizer
74
74
  end
75
75
 
76
76
  def self.reopen_log_file
77
- true #do not need it in append-only mode
77
+ if @@logger_file.respond_to?(:path)
78
+ log_file = @@logger_file.path
79
+ f = File.open(log_file, File::WRONLY | File::APPEND | File::CREAT)
80
+ f.sync = true
81
+ @@logger_file.reopen(f)
82
+ end
83
+ true
78
84
  end
79
85
 
80
86
  def self.flush_logger
@@ -100,7 +106,7 @@ module Daemonizer
100
106
  end
101
107
 
102
108
  def self.find_pools(pool_name = nil)
103
- pools = Dsl.evaluate(daemonfile)
109
+ pools = Dsl.evaluate(File.read(daemonfile.to_s), daemonfile.to_s).process
104
110
 
105
111
  if pool_name
106
112
  if pool = pools[pool_name.to_sym]
@@ -109,6 +109,19 @@ module Daemonizer
109
109
  end
110
110
  end
111
111
 
112
+ desc "logrotate", "Reopen all log files"
113
+ def logrotate(pool_name = nil)
114
+ control_pools_loop(pool_name, "log file reopened") do |pool|
115
+ # Pid file check
116
+ unless Daemonize.check_pid(pool.pid_file)
117
+ print_pool pool.name, "not started!"
118
+ exit(1)
119
+ end
120
+
121
+ Process.kill('HUP', Daemonize.read_pid(pool.pid_file))
122
+ end
123
+ end
124
+
112
125
  private
113
126
  def control_pools_loop(pool_name, message = nil, debug = false, &block)
114
127
  if debug
@@ -122,7 +135,7 @@ module Daemonizer
122
135
  else
123
136
  Daemonizer.find_pools(pool_name).each do |pool|
124
137
  Process.fork do
125
- Daemonizer.init_logger(pool.name.to_s, pool.log_file)
138
+ Daemonizer.init_logger(pool.log_file)
126
139
  yield(pool)
127
140
  end
128
141
  Process.wait
@@ -62,7 +62,7 @@ module Daemonizer
62
62
  raise ConfigError, "Log level should be one of [#{VALID_LOG_LEVELS.map(&:to_s).join(',')}]" unless VALID_LOG_LEVELS.include?(@options[:log_level].to_sym)
63
63
  if @options[:handler]
64
64
  raise ConfigError, "Handler should be a class" unless @options[:handler].is_a?(Class)
65
- raise ConfigError, "Handler should respond to :start" unless @options[:handler].public_instance_methods.include?('start')
65
+ raise ConfigError, "Handler should respond to :start" unless @options[:handler].public_instance_methods.map(&:to_sym).include?(:start)
66
66
  raise ConfigError, "Handler set. Don't use :start and :before init in Demfile" if @options[:prepare] || @options[:start]
67
67
  else
68
68
  if @options[:prepare]
@@ -84,7 +84,7 @@ module Daemonizer
84
84
 
85
85
  [:log_file, :pid_file].each do |method|
86
86
  define_method method do
87
- File.join(Daemonizer.root, @options[method.to_sym])
87
+ File.expand_path(@options[method.to_sym], Daemonizer.root)
88
88
  end
89
89
  end
90
90
 
@@ -1,10 +1,22 @@
1
1
  class Daemonizer::Dsl
2
2
  class DslError < StandardError; end
3
3
 
4
- def self.evaluate(gemfile)
4
+ def self.evaluate(daemonfile, daemonfile_name = 'Daemonfile')
5
5
  builder = new
6
- builder.instance_eval(File.read(gemfile.to_s), gemfile.to_s, 1)
7
- builder.instance_variable_get("@configs")
6
+ builder.instance_eval(daemonfile, daemonfile_name.to_s, 1)
7
+ builder
8
+ end
9
+
10
+ def configs
11
+ @configs
12
+ end
13
+
14
+ def process
15
+ result = {}
16
+ @configs.each do |k,v|
17
+ result[k] = Daemonizer::Config.new(k, v)
18
+ end
19
+ result
8
20
  end
9
21
 
10
22
  def initialize
@@ -92,7 +104,7 @@ class Daemonizer::Dsl
92
104
  @pool = name.to_sym
93
105
  options = config_copy
94
106
  yield
95
- @configs[@pool] = Daemonizer::Config.new(@pool, @options)
107
+ @configs[@pool] = @options.clone
96
108
  rescue Daemonizer::Config::ConfigError => e
97
109
  puts "* Error in pool \"#{@pool}\": #{e.to_s}. Skipping..."
98
110
  ensure
@@ -2,11 +2,11 @@ module Daemonizer
2
2
  class Engine
3
3
  attr_reader :config
4
4
 
5
- def initialize(config, debug = false)
5
+ def initialize(config)
6
6
  @config = config
7
7
  Daemonizer.logger_context = "#{Process.pid}/monitor"
8
8
  end
9
-
9
+
10
10
  def run_callback(callback, *args)
11
11
  if callbacks = @config.callbacks[callback.to_sym] and callbacks.any?
12
12
  Daemonizer.logger.info "Running :#{callback} callbacks"
@@ -15,22 +15,22 @@ module Daemonizer
15
15
  end
16
16
  end
17
17
  end
18
-
19
- def start!
20
- @pm = ProcessManager.new(@config)
21
18
 
22
- init_block = Proc.new do
23
- begin
24
- @pm.start_workers do |process_id|
25
- @config.handler.worker_id = process_id
26
- @config.handler.workers_count = @config.workers
27
- run_callback :before_start, @config.pool, process_id, @config.workers
28
- @config.handler.start
29
- end
30
- rescue Exception => e
31
- log_error(e)
32
- end
19
+ def run_prepare_with_callbacks(&block)
20
+ run_callback :before_prepare, @config.pool
21
+ Daemonizer.logger.info "Workers count is #{@config.workers}"
22
+ @config.handler.prepare(block) do
23
+ run_callback :after_prepare, @config.pool
33
24
  end
25
+ end
26
+
27
+ def run_start_with_callbacks
28
+ run_callback :before_start, @config.pool, @config.handler.worker_id, @config.handler.workers_count
29
+ @config.handler.start
30
+ end
31
+
32
+ def start!
33
+ @pm = ProcessManager.new(@config)
34
34
 
35
35
  begin
36
36
  if @config.cow_friendly
@@ -42,16 +42,22 @@ module Daemonizer
42
42
  end
43
43
  end
44
44
  @config.handler.logger = Daemonizer.logger
45
- run_callback :before_prepare, @config.pool
46
- Daemonizer.logger.info "Workers count is #{config.workers}"
47
- @config.handler.prepare(init_block) do
48
- run_callback :after_prepare, @config.pool
45
+ run_prepare_with_callbacks do
46
+ begin
47
+ @pm.start_workers do |process_id|
48
+ @config.handler.worker_id = process_id
49
+ @config.handler.workers_count = @config.workers
50
+ run_start_with_callbacks
51
+ end
52
+ rescue Exception => e
53
+ log_error(e)
54
+ end
49
55
  end
50
56
  rescue Exception => e
51
57
  log_error(e)
52
58
  end
53
59
  # Start monitoring loop
54
-
60
+
55
61
  setup_signals
56
62
  @pm.monitor_workers
57
63
  end
@@ -59,28 +65,22 @@ module Daemonizer
59
65
  def debug!
60
66
  Daemonizer.init_console_logger('console')
61
67
  @config.handler.logger = Daemonizer.logger
62
-
63
- init_block = Proc.new do
64
- begin
65
- @config.handler.worker_id = 1
66
- @config.handler.workers_count = 1
67
- run_callback :before_start, @config.pool, 1, 1
68
- @config.handler.start
69
- rescue Exception => e
70
- log_error(e)
71
- end
72
- end
73
68
 
74
69
  begin
75
- run_callback :before_prepare, @config.pool
76
- @config.handler.prepare(init_block) do
77
- run_callback :after_prepare, @config.pool
70
+ run_prepare_with_callbacks do
71
+ begin
72
+ @config.handler.worker_id = 1
73
+ @config.handler.workers_count = 1
74
+ run_start_with_callbacks
75
+ rescue Exception => e
76
+ log_error(e)
77
+ end
78
78
  end
79
79
  rescue Exception => e
80
80
  log_error(e)
81
81
  end
82
82
  end
83
-
83
+
84
84
  def log_error(e)
85
85
  Daemonizer.logger.fatal e.to_s
86
86
  Daemonizer.logger.fatal "#{e.class}: #{e}\n" + e.backtrace.join("\n")
@@ -96,6 +96,11 @@ module Daemonizer
96
96
  trap('TERM', stop)
97
97
  trap('INT', stop)
98
98
  trap('EXIT', stop)
99
+
100
+ trap('SIGHUP') do
101
+ Daemonizer.reopen_log_file
102
+ @pm.send_signal_to_workers('SIGHUP')
103
+ end
99
104
  end
100
105
 
101
106
  end
@@ -1,7 +1,7 @@
1
1
  module Daemonizer
2
2
  class Option
3
3
  class OptionError < StandardError; end
4
-
4
+
5
5
  def initialize(option, value, auto_eval = false)
6
6
  @option = option
7
7
  @value = value
@@ -10,11 +10,17 @@ module Daemonizer
10
10
  raise OptionError, "auto_apply can be used only with callable option"
11
11
  end
12
12
  end
13
-
13
+
14
14
  def value(handler = nil)
15
- if @auto_eval && @value.is_a?(Proc)
15
+ if @auto_eval && @value.is_a?(Proc)
16
16
  if handler && handler.worker_id && handler.workers_count
17
- return @value.call(handler.worker_id, handler.workers_count)
17
+ if @value.arity == 0 || @value.arity == -1
18
+ return @value.call
19
+ elsif @value.arity == 2
20
+ return @value.call(handler.worker_id, handler.workers_count)
21
+ else
22
+ raise OptionError, "option lambda should accept 0 or 2 parameters"
23
+ end
18
24
  else
19
25
  raise OptionError, "value called before handler initialized"
20
26
  end
@@ -22,6 +28,6 @@ module Daemonizer
22
28
  @value
23
29
  end
24
30
  end
25
-
31
+
26
32
  end
27
33
  end