daemon-kit 0.1.5.1 → 0.1.6
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/Manifest.txt +7 -1
- data/app_generators/daemon_kit/daemon_kit_generator.rb +7 -3
- data/app_generators/daemon_kit/templates/config/environment.rb +4 -0
- data/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
- data/app_generators/daemon_kit/templates/config/{initializers → pre-daemonize}/readme +2 -1
- data/app_generators/daemon_kit/templates/lib/daemon.rb +2 -1
- data/daemon_generators/amqp/amqp_generator.rb +2 -2
- data/daemon_generators/cron/cron_generator.rb +2 -2
- data/daemon_generators/jabber/jabber_generator.rb +2 -2
- data/daemon_generators/nanite_agent/nanite_agent_generator.rb +1 -1
- data/lib/daemon_kit.rb +2 -1
- data/lib/daemon_kit/application.rb +4 -2
- data/lib/daemon_kit/config.rb +5 -0
- data/lib/daemon_kit/error_handlers/base.rb +32 -0
- data/lib/daemon_kit/error_handlers/hoptoad.rb +61 -0
- data/lib/daemon_kit/error_handlers/mail.rb +48 -0
- data/lib/daemon_kit/initializer.rb +66 -25
- data/lib/daemon_kit/nanite/agent.rb +2 -2
- data/lib/daemon_kit/safety.rb +85 -0
- data/lib/daemon_kit/tasks/environment.rake +9 -0
- data/lib/daemon_kit/tasks/framework.rake +34 -3
- data/rubygems_generators/install_rspec/templates/spec/spec_helper.rb +1 -0
- data/rubygems_generators/install_rspec/templates/tasks/rspec.rake +1 -1
- data/test/test_amqp_generator.rb +1 -1
- data/test/test_daemon-kit_generator.rb +4 -2
- data/test/test_jabber_generator.rb +1 -1
- metadata +9 -3
data/Manifest.txt
CHANGED
@@ -14,7 +14,8 @@ app_generators/daemon_kit/templates/config/environment.rb
|
|
14
14
|
app_generators/daemon_kit/templates/config/environments/development.rb
|
15
15
|
app_generators/daemon_kit/templates/config/environments/production.rb
|
16
16
|
app_generators/daemon_kit/templates/config/environments/test.rb
|
17
|
-
app_generators/daemon_kit/templates/config/
|
17
|
+
app_generators/daemon_kit/templates/config/post-daemonize/readme
|
18
|
+
app_generators/daemon_kit/templates/config/pre-daemonize/readme
|
18
19
|
app_generators/daemon_kit/templates/lib/daemon.rb
|
19
20
|
app_generators/daemon_kit/templates/libexec/daemon.erb
|
20
21
|
bin/daemon_kit
|
@@ -43,12 +44,17 @@ lib/daemon_kit/amqp.rb
|
|
43
44
|
lib/daemon_kit/application.rb
|
44
45
|
lib/daemon_kit/config.rb
|
45
46
|
lib/daemon_kit/cron.rb
|
47
|
+
lib/daemon_kit/error_handlers/base.rb
|
48
|
+
lib/daemon_kit/error_handlers/hoptoad.rb
|
49
|
+
lib/daemon_kit/error_handlers/mail.rb
|
46
50
|
lib/daemon_kit/initializer.rb
|
47
51
|
lib/daemon_kit/jabber.rb
|
48
52
|
lib/daemon_kit/nanite.rb
|
49
53
|
lib/daemon_kit/nanite/agent.rb
|
50
54
|
lib/daemon_kit/patches/force_kill_wait.rb
|
55
|
+
lib/daemon_kit/safety.rb
|
51
56
|
lib/daemon_kit/tasks.rb
|
57
|
+
lib/daemon_kit/tasks/environment.rake
|
52
58
|
lib/daemon_kit/tasks/framework.rake
|
53
59
|
rubygems_generators/install_rspec/USAGE
|
54
60
|
rubygems_generators/install_rspec/install_rspec_generator.rb
|
@@ -60,15 +60,19 @@ class DaemonKitGenerator < RubiGen::Base
|
|
60
60
|
m.template "config/environment.rb", "config/environment.rb"
|
61
61
|
m.directory "config/environments"
|
62
62
|
%w{ development test production }.each { |f| m.file "config/environments/#{f}.rb", "config/environments/#{f}.rb" }
|
63
|
-
m.directory "config/
|
64
|
-
m.file "config/
|
63
|
+
m.directory "config/pre-daemonize"
|
64
|
+
m.file "config/pre-daemonize/readme", "config/pre-daemonize/readme"
|
65
|
+
m.directory "config/post-daemonize"
|
66
|
+
m.file "config/post-daemonize/readme", "config/post-daemonize/readme"
|
65
67
|
|
66
68
|
# Libraries
|
67
69
|
m.directory "lib"
|
68
70
|
m.file "lib/daemon.rb", "lib/#{daemon_name}.rb"
|
69
71
|
|
70
|
-
#
|
72
|
+
# Tasks
|
71
73
|
m.directory "tasks"
|
74
|
+
|
75
|
+
# Tests
|
72
76
|
m.dependency "install_rspec", [daemon_name], :destination => destination_root, :collision => :force
|
73
77
|
|
74
78
|
# Others
|
@@ -16,4 +16,8 @@ DaemonKit::Initializer.run do |config|
|
|
16
16
|
|
17
17
|
# Force the daemon to be killed after X seconds from asking it to
|
18
18
|
# config.force_kill_wait = 30
|
19
|
+
|
20
|
+
# Configure the safety net (see DaemonKit::Safety)
|
21
|
+
# config.safety_net.handler = :mail # (or :hoptoad )
|
22
|
+
# config.safety_net.mail.host = 'localhost'
|
19
23
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# You can place files in here to be loaded before the code is daemonized.
|
2
2
|
#
|
3
3
|
# DaemonKit looks for a file named '<config.daemon_name>.rb' and loads
|
4
|
-
# that file
|
4
|
+
# that file first, and inside a DaemonKit::Initializer block. The
|
5
|
+
# remaning files then simply required into the running process.
|
5
6
|
#
|
6
7
|
# These files are mostly useful for operations that should fail blatantly
|
7
8
|
# before daemonizing, like loading gems.
|
@@ -1 +1,2 @@
|
|
1
|
-
# Your starting point for daemon specific classes
|
1
|
+
# Your starting point for daemon specific classes. This directory is
|
2
|
+
# already included in your load path, so no need to specify it.
|
@@ -15,7 +15,7 @@ class AmqpGenerator < RubiGen::Base
|
|
15
15
|
record do |m|
|
16
16
|
# Ensure appropriate folder(s) exists
|
17
17
|
m.directory ''
|
18
|
-
|
18
|
+
|
19
19
|
# Create stubs
|
20
20
|
# m.template "template.rb.erb", "some_file_after_erb.rb"
|
21
21
|
# m.template_copy_each ["template.rb", "template2.rb"]
|
@@ -32,7 +32,7 @@ class AmqpGenerator < RubiGen::Base
|
|
32
32
|
|
33
33
|
# Copy over our daemon
|
34
34
|
m.directory 'libexec'
|
35
|
-
m.template 'libexec/daemon.rb', "libexec/#{name}.rb"
|
35
|
+
m.template 'libexec/daemon.rb', "libexec/#{name}-daemon.rb"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -23,7 +23,7 @@ class CronGenerator < RubiGen::Base
|
|
23
23
|
# m.file "file", "some_file_copied"
|
24
24
|
# m.file_copy_each ["path/to/file", "path/to/file2"]
|
25
25
|
# m.file_copy_each ["path/to/file", "path/to/file2"], "some/path"
|
26
|
-
|
26
|
+
|
27
27
|
# Copy over configs
|
28
28
|
m.directory 'config'
|
29
29
|
m.directory 'config/initializers'
|
@@ -31,7 +31,7 @@ class CronGenerator < RubiGen::Base
|
|
31
31
|
|
32
32
|
# Copy over our daemon
|
33
33
|
m.directory 'libexec'
|
34
|
-
m.template 'libexec/daemon.rb', "libexec/#{name}.rb"
|
34
|
+
m.template 'libexec/daemon.rb', "libexec/#{name}-daemon.rb"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -23,7 +23,7 @@ class JabberGenerator < RubiGen::Base
|
|
23
23
|
# m.file "file", "some_file_copied"
|
24
24
|
# m.file_copy_each ["path/to/file", "path/to/file2"]
|
25
25
|
# m.file_copy_each ["path/to/file", "path/to/file2"], "some/path"
|
26
|
-
|
26
|
+
|
27
27
|
# Copy over our configs
|
28
28
|
m.directory 'config'
|
29
29
|
m.template 'config/jabber.yml', 'config/jabber.yml'
|
@@ -32,7 +32,7 @@ class JabberGenerator < RubiGen::Base
|
|
32
32
|
|
33
33
|
# Copy over our daemon
|
34
34
|
m.directory 'libexec'
|
35
|
-
m.template 'libexec/daemon.rb', "libexec/#{name}.rb"
|
35
|
+
m.template 'libexec/daemon.rb', "libexec/#{name}-daemon.rb"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
data/lib/daemon_kit.rb
CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
4
4
|
require 'rubygems'
|
5
5
|
|
6
6
|
module DaemonKit
|
7
|
-
VERSION = '0.1.
|
7
|
+
VERSION = '0.1.6'
|
8
8
|
|
9
9
|
autoload :Initializer, 'daemon_kit/initializer'
|
10
10
|
autoload :Application, 'daemon_kit/application'
|
@@ -13,4 +13,5 @@ module DaemonKit
|
|
13
13
|
autoload :Jabber, 'daemon_kit/jabber'
|
14
14
|
autoload :AMQP, 'daemon_kit/amqp'
|
15
15
|
autoload :Nanite, 'daemon_kit/nanite'
|
16
|
+
autoload :Safety, 'daemon_kit/safety'
|
16
17
|
end
|
@@ -14,8 +14,8 @@ module DaemonKit
|
|
14
14
|
app_name = DaemonKit.configuration.daemon_name || File.basename( file )
|
15
15
|
options = { :backtrace => true, :log_output => true, :app_name => app_name }
|
16
16
|
|
17
|
-
options[:dir_mode] = DaemonKit.configuration.dir_mode
|
18
|
-
options[:dir] = DaemonKit.configuration.dir
|
17
|
+
options[:dir_mode] = DaemonKit.configuration.dir_mode
|
18
|
+
options[:dir] = DaemonKit.configuration.dir
|
19
19
|
options[:multiple] = DaemonKit.configuration.multiple
|
20
20
|
options[:force_kill_wait] = DaemonKit.configuration.force_kill_wait if DaemonKit.configuration.force_kill_wait
|
21
21
|
|
@@ -26,6 +26,8 @@ module DaemonKit
|
|
26
26
|
# initialization process
|
27
27
|
def running!
|
28
28
|
DaemonKit::Initializer.continue!
|
29
|
+
|
30
|
+
yield DaemonKit.configuration if block_given?
|
29
31
|
end
|
30
32
|
|
31
33
|
end
|
data/lib/daemon_kit/config.rb
CHANGED
@@ -29,6 +29,11 @@ module DaemonKit
|
|
29
29
|
new( YAML.load_file( path ) )
|
30
30
|
end
|
31
31
|
|
32
|
+
# Return the +config+.yml file as a raw hash.
|
33
|
+
def hash( config, symbolize = false )
|
34
|
+
self.load( config ).to_h( symbolize )
|
35
|
+
end
|
36
|
+
|
32
37
|
end
|
33
38
|
|
34
39
|
# Expects a hash, looks for DAEMON_ENV key
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module DaemonKit
|
2
|
+
module ErrorHandlers
|
3
|
+
# Error handlers in DaemonKit are used by the #Safety class. Any
|
4
|
+
# error handler has to support the interface provided by this
|
5
|
+
# class. It's also required that safety handlers implement a
|
6
|
+
# singleton approach (handled by default by #Base).
|
7
|
+
class Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
@instance = nil
|
12
|
+
|
13
|
+
def instance
|
14
|
+
@instance ||= new
|
15
|
+
end
|
16
|
+
private :new
|
17
|
+
|
18
|
+
# When we're inherited, immediately register the handler with
|
19
|
+
# the safety net
|
20
|
+
def inherited( child ) #:nodoc:
|
21
|
+
Safety.register_error_handler( child )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Error handlers should overwrite this method and implement
|
26
|
+
# their own reporting method.
|
27
|
+
def handle_exception( exception )
|
28
|
+
raise NoMethodError, "Error handler doesn't support #handle_exception"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module DaemonKit
|
4
|
+
module ErrorHandlers
|
5
|
+
# Error reporting via Hoptoad.
|
6
|
+
class Hoptoad < Base
|
7
|
+
|
8
|
+
# Your hoptoad API key
|
9
|
+
@api_key = nil
|
10
|
+
attr_accessor :api_key
|
11
|
+
|
12
|
+
def handle_exception( exception )
|
13
|
+
headers = {
|
14
|
+
'Content-type' => 'application/x-yaml',
|
15
|
+
'Accept' => 'text/xml, application/xml'
|
16
|
+
}
|
17
|
+
|
18
|
+
http = Net::HTTP.new( url.host, url.port )
|
19
|
+
data = clean_exception( exception )
|
20
|
+
|
21
|
+
response = begin
|
22
|
+
http.post( url.path, data.to_yaml, headers )
|
23
|
+
rescue TimoutError => e
|
24
|
+
DaemonKit.logger.error("Timeout while contacting the Hoptoad server.")
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
case response
|
28
|
+
when Net::HTTPSuccess then
|
29
|
+
DaemonKit.logger.info "Hoptoad Success: #{response.class}"
|
30
|
+
else
|
31
|
+
DaemonKit.logger.error "Hoptoad Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def url
|
36
|
+
URI.parse("http://hoptoadapp.com/notices/")
|
37
|
+
end
|
38
|
+
|
39
|
+
def clean_exception( exception )
|
40
|
+
data = {
|
41
|
+
:api_key => self.api_key,
|
42
|
+
:error_class => exception.class.name,
|
43
|
+
:error_message => "#{exception.class.name}: #{exception.message}",
|
44
|
+
:backtrace => exception.backtrace,
|
45
|
+
:environment => ENV.to_hash,
|
46
|
+
:request => [],
|
47
|
+
:session => []
|
48
|
+
}
|
49
|
+
|
50
|
+
stringify_keys( data )
|
51
|
+
end
|
52
|
+
|
53
|
+
def stringify_keys(hash) #:nodoc:
|
54
|
+
hash.inject({}) do |h, pair|
|
55
|
+
h[pair.first.to_s] = pair.last.is_a?(Hash) ? stringify_keys(pair.last) : pair.last
|
56
|
+
h
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module DaemonKit
|
4
|
+
module ErrorHandlers
|
5
|
+
# Send an email notification of the exception via SMTP
|
6
|
+
class Mail < Base
|
7
|
+
|
8
|
+
# SMTP hostname
|
9
|
+
@host = 'localhost'
|
10
|
+
attr_accessor :host
|
11
|
+
|
12
|
+
# Recipients of the notification
|
13
|
+
@recipients = []
|
14
|
+
attr_accessor :recipients
|
15
|
+
|
16
|
+
# Subject prefix
|
17
|
+
@prefix = '[DAEMON-KIT]'
|
18
|
+
attr_accessor :prefix
|
19
|
+
|
20
|
+
# Sender address
|
21
|
+
@sender = 'daemon-kit'
|
22
|
+
attr_accessor :sender
|
23
|
+
|
24
|
+
def handle_exception( exception )
|
25
|
+
email = <<EOF
|
26
|
+
To: #{self.recipients.map { |r| '<' + r + '>' }.join(', ')}
|
27
|
+
From: <#{self.sender}>
|
28
|
+
Subject: #{self.prefix} #{exception.message}
|
29
|
+
Date: #{Time.now}
|
30
|
+
|
31
|
+
DaemonKit caught an exception inside #{DaemonKit.configuration.daemon_name}.
|
32
|
+
|
33
|
+
Message: #{exception.message}
|
34
|
+
Backtrace:
|
35
|
+
#{exception.backtrace.join("\n ")}
|
36
|
+
|
37
|
+
Environment: #{ENV.inspect}
|
38
|
+
EOF
|
39
|
+
begin
|
40
|
+
Net::SMTP.start( self.host ) do |smtp|
|
41
|
+
smtp.send_message( email, self.sender, self.recipients )
|
42
|
+
end
|
43
|
+
rescue
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -29,16 +29,23 @@ module DaemonKit
|
|
29
29
|
def trap( *args, &block )
|
30
30
|
self.configuration.trap( *args, &block )
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
|
+
def framework_root
|
34
|
+
File.join( File.dirname(__FILE__), '..', '..' )
|
35
|
+
end
|
36
|
+
|
37
|
+
def root
|
38
|
+
DAEMON_ROOT
|
39
|
+
end
|
33
40
|
end
|
34
|
-
|
41
|
+
|
35
42
|
|
36
43
|
# This class does all the nightmare work of setting up a working
|
37
44
|
# environment for your daemon.
|
38
45
|
class Initializer
|
39
46
|
|
40
47
|
attr_reader :configuration
|
41
|
-
|
48
|
+
|
42
49
|
def self.run( configuration = Configuration.new )
|
43
50
|
yield configuration if block_given?
|
44
51
|
initializer = new configuration
|
@@ -55,25 +62,29 @@ module DaemonKit
|
|
55
62
|
DaemonKit.logger.warn "Shutting down"
|
56
63
|
exit
|
57
64
|
end
|
58
|
-
|
65
|
+
|
59
66
|
def initialize( configuration )
|
60
67
|
@configuration = configuration
|
61
68
|
end
|
62
69
|
|
63
70
|
def before_daemonize
|
64
71
|
DaemonKit.configuration = @configuration
|
65
|
-
|
72
|
+
|
66
73
|
set_load_path
|
67
74
|
load_gems
|
68
75
|
load_patches
|
69
76
|
load_environment
|
77
|
+
load_predaemonize_configs
|
70
78
|
end
|
71
79
|
|
72
80
|
def after_daemonize
|
73
81
|
initialize_logger
|
74
82
|
initialize_signal_traps
|
83
|
+
|
84
|
+
include_core_lib
|
85
|
+
load_postdaemonize_configs
|
75
86
|
end
|
76
|
-
|
87
|
+
|
77
88
|
def set_load_path
|
78
89
|
configuration.load_paths.each do |d|
|
79
90
|
$:.unshift( "#{DAEMON_ROOT}/#{d}" ) if File.directory?( "#{DAEMON_ROOT}/#{d}" )
|
@@ -81,7 +92,7 @@ module DaemonKit
|
|
81
92
|
end
|
82
93
|
|
83
94
|
def load_gems
|
84
|
-
|
95
|
+
|
85
96
|
end
|
86
97
|
|
87
98
|
def load_patches
|
@@ -93,22 +104,36 @@ module DaemonKit
|
|
93
104
|
def load_environment
|
94
105
|
return if @environment_loaded
|
95
106
|
@environment_loaded = true
|
96
|
-
|
107
|
+
|
97
108
|
config = configuration
|
98
|
-
|
109
|
+
|
99
110
|
eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
|
100
|
-
|
111
|
+
|
101
112
|
eval(IO.read(configuration.daemon_initializer), binding, configuration.daemon_initializer) if File.exist?( configuration.daemon_initializer )
|
102
113
|
end
|
103
114
|
|
115
|
+
def load_predaemonize_configs
|
116
|
+
Dir[ File.join( DAEMON_ROOT, 'config', 'pre-daemonize', '*.rb' ) ].each do |f|
|
117
|
+
next if File.basename( f ) == File.basename( configuration.daemon_initializer )
|
118
|
+
|
119
|
+
require f
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def load_postdaemonize_configs
|
124
|
+
Dir[ File.join( DAEMON_ROOT, 'config', 'post-daemonize', '*.rb' ) ].each do |f|
|
125
|
+
require f
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
104
129
|
def initialize_logger
|
105
130
|
return if DaemonKit.logger
|
106
|
-
|
131
|
+
|
107
132
|
unless logger = configuration.logger
|
108
133
|
logger = Logger.new( configuration.log_path )
|
109
134
|
logger.level = configuration.log_level
|
110
135
|
end
|
111
|
-
|
136
|
+
|
112
137
|
DaemonKit.logger = logger
|
113
138
|
|
114
139
|
configuration.trap("USR1") {
|
@@ -128,9 +153,14 @@ module DaemonKit
|
|
128
153
|
configuration.trap( 'INT', term_proc )
|
129
154
|
configuration.trap( 'TERM', term_proc )
|
130
155
|
end
|
131
|
-
|
156
|
+
|
157
|
+
def include_core_lib
|
158
|
+
if File.exists?( core_lib = File.join( DAEMON_ROOT, 'lib', configuration.daemon_name + '.rb' ) )
|
159
|
+
require core_lib
|
160
|
+
end
|
161
|
+
end
|
132
162
|
end
|
133
|
-
|
163
|
+
|
134
164
|
# Holds our various configuration values
|
135
165
|
class Configuration
|
136
166
|
# Root to the daemon
|
@@ -145,7 +175,7 @@ module DaemonKit
|
|
145
175
|
# Path to the log file, defaults to 'log/<environment>.log'
|
146
176
|
attr_accessor :log_path
|
147
177
|
|
148
|
-
# :system,
|
178
|
+
# :system,
|
149
179
|
attr_accessor :dir_mode
|
150
180
|
|
151
181
|
# Path to the log file, defaults to 'log/<environment>.log'
|
@@ -166,9 +196,13 @@ module DaemonKit
|
|
166
196
|
# Collection of signal traps
|
167
197
|
attr_reader :signal_traps
|
168
198
|
|
199
|
+
# Our safety net (#Safety) instance
|
200
|
+
attr_accessor :safety_net
|
201
|
+
|
169
202
|
def initialize
|
170
203
|
set_root_path!
|
171
|
-
|
204
|
+
set_daemon_defaults!
|
205
|
+
|
172
206
|
self.load_paths = default_load_paths
|
173
207
|
self.log_level = default_log_level
|
174
208
|
self.log_path = default_log_path
|
@@ -176,6 +210,8 @@ module DaemonKit
|
|
176
210
|
self.multiple = false
|
177
211
|
self.force_kill_wait = false
|
178
212
|
|
213
|
+
self.safety_net = DaemonKit::Safety.instance
|
214
|
+
|
179
215
|
@signal_traps = {}
|
180
216
|
end
|
181
217
|
|
@@ -192,25 +228,25 @@ module DaemonKit
|
|
192
228
|
def daemon_initializer
|
193
229
|
"#{root_path}/config/initializers/#{self.daemon_name}.rb"
|
194
230
|
end
|
195
|
-
|
231
|
+
|
196
232
|
# Add a trap for the specified signal, can be code block or a proc
|
197
233
|
def trap( signal, proc = nil, &block )
|
198
234
|
return if proc.nil? && !block_given?
|
199
|
-
|
235
|
+
|
200
236
|
unless @signal_traps.has_key?( signal )
|
201
237
|
set_trap( signal )
|
202
238
|
end
|
203
|
-
|
239
|
+
|
204
240
|
@signal_traps[signal].unshift( proc || block )
|
205
241
|
end
|
206
|
-
|
242
|
+
|
207
243
|
protected
|
208
244
|
|
209
245
|
def run_traps( signal )
|
210
246
|
DaemonKit.logger.info "Running signal traps for #{signal}"
|
211
247
|
self.signal_traps[ signal ].each { |trap| trap.call }
|
212
248
|
end
|
213
|
-
|
249
|
+
|
214
250
|
private
|
215
251
|
|
216
252
|
def set_trap( signal )
|
@@ -218,7 +254,7 @@ module DaemonKit
|
|
218
254
|
@signal_traps[ signal ] = []
|
219
255
|
Signal.trap( signal, Proc.new { self.run_traps( signal ) } )
|
220
256
|
end
|
221
|
-
|
257
|
+
|
222
258
|
def set_root_path!
|
223
259
|
raise "DAEMON_ROOT is not set" unless defined?(::DAEMON_ROOT)
|
224
260
|
raise "DAEMON_ROOT is not a directory" unless defined?(::DAEMON_ROOT)
|
@@ -238,10 +274,15 @@ module DaemonKit
|
|
238
274
|
::DAEMON_ROOT.replace @root_path
|
239
275
|
end
|
240
276
|
|
277
|
+
def set_daemon_defaults!
|
278
|
+
self.dir_mode = :normal
|
279
|
+
self.dir = File.join( DAEMON_ROOT, 'log' )
|
280
|
+
end
|
281
|
+
|
241
282
|
def default_load_paths
|
242
283
|
[ 'lib' ]
|
243
284
|
end
|
244
|
-
|
285
|
+
|
245
286
|
def default_log_path
|
246
287
|
File.join(root_path, 'log', "#{environment}.log")
|
247
288
|
end
|
@@ -250,6 +291,6 @@ module DaemonKit
|
|
250
291
|
environment == 'production' ? Logger::INFO : Logger::DEBUG
|
251
292
|
end
|
252
293
|
end
|
253
|
-
|
254
|
-
|
294
|
+
|
295
|
+
|
255
296
|
end
|
@@ -20,7 +20,7 @@ module DaemonKit
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def initialize
|
23
|
-
@config = DaemonKit::Config.load( 'nanite' )
|
23
|
+
@config = DaemonKit::Config.load( 'nanite' ).to_h( true )
|
24
24
|
|
25
25
|
config_agent
|
26
26
|
end
|
@@ -33,7 +33,7 @@ module DaemonKit
|
|
33
33
|
# Start our mapper
|
34
34
|
mapper_thread = Thread.new do
|
35
35
|
EM.run do
|
36
|
-
agent = ::Nanite.start_agent( @config
|
36
|
+
agent = ::Nanite.start_agent( @config )
|
37
37
|
block.call( agent ) if block
|
38
38
|
end
|
39
39
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module DaemonKit
|
2
|
+
# Provides a wrapper for running code inside a 'safety net' Any
|
3
|
+
# exceptions raised inside a safety net is handled and reported via
|
4
|
+
# loggers, email or Hoptoad.
|
5
|
+
#
|
6
|
+
# The safety net can be configured via DaemonKit.config.safety,
|
7
|
+
# which holds the only instance of the safety net.
|
8
|
+
class Safety
|
9
|
+
|
10
|
+
# Who get's notified.
|
11
|
+
@handler = nil
|
12
|
+
attr_accessor :handler
|
13
|
+
|
14
|
+
# Registered error handlers
|
15
|
+
@error_handlers = {}
|
16
|
+
attr_reader :error_handlers
|
17
|
+
|
18
|
+
class << self
|
19
|
+
|
20
|
+
# Singleton
|
21
|
+
@instance = nil
|
22
|
+
|
23
|
+
def instance
|
24
|
+
@instance ||= new
|
25
|
+
end
|
26
|
+
private :new
|
27
|
+
|
28
|
+
# Run the provided block inside a safety net.
|
29
|
+
def run(&block)
|
30
|
+
self.instance.run(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def register_error_handler( klass )
|
34
|
+
name = klass.to_s.split('::').last.downcase
|
35
|
+
|
36
|
+
DaemonKit.logger.debug( "Registering error handler '#{name}' (#{klass})" ) if DaemonKit.logger
|
37
|
+
|
38
|
+
instance.instance_eval( <<-EOF, __FILE__, __LINE__ )
|
39
|
+
def #{name}
|
40
|
+
@#{name} ||= #{klass}.instance
|
41
|
+
end
|
42
|
+
EOF
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Run the provided block inside a safety net.
|
47
|
+
def run(&block)
|
48
|
+
begin
|
49
|
+
block.call
|
50
|
+
rescue => e
|
51
|
+
# Log
|
52
|
+
DaemonKit.logger.fatal "Safety net caught exception: #{e.message}"
|
53
|
+
DaemonKit.logger.fatal "Backtrace: #{e.backtrace.join("\n ")}"
|
54
|
+
|
55
|
+
get_handler.handle_exception( e ) if get_handler
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_handler
|
60
|
+
if @handler && self.respond_to?( @handler )
|
61
|
+
h = send( @handler )
|
62
|
+
return h if h.class.ancestors.include?( DaemonKit::ErrorHandlers::Base )
|
63
|
+
end
|
64
|
+
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Object
|
71
|
+
class << self
|
72
|
+
def safely(&block)
|
73
|
+
DaemonKit::Safety.run(&block)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def safely(&block)
|
78
|
+
DaemonKit::Safety.run(&block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Load our error handlers
|
83
|
+
require 'daemon_kit/error_handlers/base'
|
84
|
+
require 'daemon_kit/error_handlers/mail'
|
85
|
+
require 'daemon_kit/error_handlers/hoptoad'
|
@@ -0,0 +1,9 @@
|
|
1
|
+
task :environment do
|
2
|
+
# This relies on the fact that rake changes the currect working
|
3
|
+
# directory to the directory where the Rakefile is located, thus
|
4
|
+
# implying DAEMON_ROOT.
|
5
|
+
DAEMON_ROOT = '.'
|
6
|
+
$daemon_kit_rake_task = true
|
7
|
+
|
8
|
+
require 'config/environment'
|
9
|
+
end
|
@@ -46,10 +46,10 @@ namespace :daemon_kit do
|
|
46
46
|
|
47
47
|
rm_rf "vendor/daemon_kit"
|
48
48
|
mkdir_p "vendor/daemon_kit"
|
49
|
-
|
49
|
+
|
50
50
|
chdir 'vendor/daemon_kit' do
|
51
51
|
latest_revision = YAML.load(open(commits))["commits"].first["id"]
|
52
|
-
|
52
|
+
|
53
53
|
puts "Downloading DaemonKit from #{url}"
|
54
54
|
File.open('daemon-kit.zip', 'wb') do |dst|
|
55
55
|
open url do |src|
|
@@ -70,6 +70,37 @@ namespace :daemon_kit do
|
|
70
70
|
touch "REVISION_#{latest_revision}"
|
71
71
|
end
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "Upgrade your local files for a daemon after upgrading daemon-kit"
|
77
|
+
task :upgrade => 'environment' do
|
78
|
+
# Run these
|
79
|
+
%w{ initializers }.each do |t|
|
80
|
+
Rake::Task["daemon_kit:upgrade:#{t}"].invoke
|
81
|
+
end
|
82
|
+
|
83
|
+
puts
|
84
|
+
puts "#{DaemonKit.configuration.daemon_name} has been upgraded."
|
74
85
|
end
|
86
|
+
|
87
|
+
namespace :upgrade do
|
88
|
+
# Upgrade the initializers
|
89
|
+
task :initializers do
|
90
|
+
if File.directory?( File.join(DaemonKit.root, 'config', 'initializers') )
|
91
|
+
mv File.join(DaemonKit.root, 'config', 'initializers'), File.join(DAEMON_ROOT, 'config', 'pre-daemonize')
|
92
|
+
copy_framework_template( 'config', 'pre-daemonize', 'readme' )
|
93
|
+
end
|
94
|
+
|
95
|
+
unless File.directory?( File.join(DAEMON_ROOT, 'config', 'post-daemonize') )
|
96
|
+
mkdir_p File.join(DAEMON_ROOT, 'config', 'post-daemonize')
|
97
|
+
copy_framework_template( 'config', 'post-daemonize', 'readme' )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def copy_framework_template( *args )
|
104
|
+
src_dir = File.join(DaemonKit.framework_root, 'app_generators', 'daemon_kit', 'templates')
|
105
|
+
cp File.join( src_dir, *args ), File.join( DaemonKit.root, *args )
|
75
106
|
end
|
data/test/test_amqp_generator.rb
CHANGED
@@ -33,7 +33,7 @@ class TestAmqpGenerator < Test::Unit::TestCase
|
|
33
33
|
assert_directory_exists "config/initializers"
|
34
34
|
assert_generated_file "config/amqp.yml"
|
35
35
|
assert_generated_file "config/initializers/myapp.rb"
|
36
|
-
assert_generated_file "libexec/myapp.rb"
|
36
|
+
assert_generated_file "libexec/myapp-daemon.rb"
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
@@ -40,8 +40,10 @@ class TestDaemonKitGenerator < Test::Unit::TestCase
|
|
40
40
|
assert_generated_file "config/environments/development.rb"
|
41
41
|
assert_generated_file "config/environments/test.rb"
|
42
42
|
assert_generated_file "config/environments/production.rb"
|
43
|
-
assert_directory_exists "config/
|
44
|
-
assert_generated_file "config/
|
43
|
+
assert_directory_exists "config/pre-daemonize"
|
44
|
+
assert_generated_file "config/pre-daemonize/readme"
|
45
|
+
assert_directory_exists "config/post-daemonize"
|
46
|
+
assert_generated_file "config/post-daemonize/readme"
|
45
47
|
assert_directory_exists "lib"
|
46
48
|
assert_generated_file "lib/#{daemon_name}.rb"
|
47
49
|
assert_directory_exists "libexec"
|
@@ -34,7 +34,7 @@ class TestJabberGenerator < Test::Unit::TestCase
|
|
34
34
|
assert_directory_exists "config/initializers"
|
35
35
|
assert_generated_file "config/initializers/myapp.rb"
|
36
36
|
assert_directory_exists "libexec"
|
37
|
-
assert_generated_file "libexec/myapp.rb"
|
37
|
+
assert_generated_file "libexec/myapp-daemon.rb"
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: daemon-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenneth Kalmer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-13 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -81,7 +81,8 @@ files:
|
|
81
81
|
- app_generators/daemon_kit/templates/config/environments/development.rb
|
82
82
|
- app_generators/daemon_kit/templates/config/environments/production.rb
|
83
83
|
- app_generators/daemon_kit/templates/config/environments/test.rb
|
84
|
-
- app_generators/daemon_kit/templates/config/
|
84
|
+
- app_generators/daemon_kit/templates/config/post-daemonize/readme
|
85
|
+
- app_generators/daemon_kit/templates/config/pre-daemonize/readme
|
85
86
|
- app_generators/daemon_kit/templates/lib/daemon.rb
|
86
87
|
- app_generators/daemon_kit/templates/libexec/daemon.erb
|
87
88
|
- bin/daemon_kit
|
@@ -110,12 +111,17 @@ files:
|
|
110
111
|
- lib/daemon_kit/application.rb
|
111
112
|
- lib/daemon_kit/config.rb
|
112
113
|
- lib/daemon_kit/cron.rb
|
114
|
+
- lib/daemon_kit/error_handlers/base.rb
|
115
|
+
- lib/daemon_kit/error_handlers/hoptoad.rb
|
116
|
+
- lib/daemon_kit/error_handlers/mail.rb
|
113
117
|
- lib/daemon_kit/initializer.rb
|
114
118
|
- lib/daemon_kit/jabber.rb
|
115
119
|
- lib/daemon_kit/nanite.rb
|
116
120
|
- lib/daemon_kit/nanite/agent.rb
|
117
121
|
- lib/daemon_kit/patches/force_kill_wait.rb
|
122
|
+
- lib/daemon_kit/safety.rb
|
118
123
|
- lib/daemon_kit/tasks.rb
|
124
|
+
- lib/daemon_kit/tasks/environment.rake
|
119
125
|
- lib/daemon_kit/tasks/framework.rake
|
120
126
|
- rubygems_generators/install_rspec/USAGE
|
121
127
|
- rubygems_generators/install_rspec/install_rspec_generator.rb
|