kennethkalmer-daemon-kit 0.1.5.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.1.6 2009-05-13
2
+
3
+ * DaemonKit::Safety class to handle the trapping and logging of
4
+ exceptions, as well as email notifications or Hoptoad notifications.
5
+ * New config/pre-daemonize and config/post-daemonize structure
6
+ * New tasks to simplify upgrading daemon-kit projects
7
+ * Fixed some other annoyances and bugs
8
+ * Bigger TODO list
9
+
1
10
  == 0.1.5 2009-05-07
2
11
 
3
12
  * DaemonKit::Config class to easy the use of YAML configs internally,
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/initializers/readme
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
data/TODO.txt CHANGED
@@ -4,7 +4,7 @@ DaemonKit TODO List
4
4
  This is purely a drop in the bucket of what has to come...
5
5
 
6
6
  * [DONE] Easy way to trap signals
7
- * Error handling to the degree Rails does
7
+ * [IN PROGRESS] Error handling to the degree Rails does
8
8
  * Easy configuration of an ORM of choice, including patching it if needed (ActiveRecord *cough*)
9
9
  * Improved generators for creating skeleton daemons:
10
10
  * [DONE] Jabber bot
@@ -14,6 +14,7 @@ This is purely a drop in the bucket of what has to come...
14
14
  * Queue (SQS, AMQP, etc) pollers
15
15
  * Rake tasks for generating:
16
16
  * god configs
17
+ * Sys-V style init scripts
17
18
  * Pre-built capistrano configs for easy deployment
18
19
  * Support for dropping privileges
19
20
  * Support for chroot'ing
@@ -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/initializers"
64
- m.file "config/initializers/readme", "config/initializers/readme"
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
- # Tests
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
@@ -0,0 +1,5 @@
1
+ # You can place files in here to be loaded after the code is daemonized.
2
+ #
3
+ # All the files placed here will just be required into the running
4
+ # process. This is the correct place to open any IO objects, establish
5
+ # database connections, etc.
@@ -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 with as if inside a DaemonKit::Initializer block.
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
 
@@ -35,7 +35,7 @@ class NaniteAgentGenerator < RubiGen::Base
35
35
 
36
36
  # Copy over our daemon
37
37
  m.directory 'libexec'
38
- m.template 'libexec/daemon.rb', "libexec/#{name}.rb"
38
+ m.template 'libexec/daemon.rb', "libexec/#{name}-daemon.rb"
39
39
  end
40
40
  end
41
41
 
@@ -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 || :normal
18
- options[:dir] = DaemonKit.configuration.dir || "log"
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
@@ -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.to_h( true ) )
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/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.5.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
@@ -7,6 +7,7 @@ rescue LoadError
7
7
  end
8
8
 
9
9
  require File.dirname(__FILE__) + '/../config/boot'
10
+ DaemonKit::Application.running!
10
11
  require '<%= gem_name %>'
11
12
 
12
13
  Spec::Runner.configure do |config|
@@ -14,7 +14,7 @@ EOS
14
14
  exit(0)
15
15
  end
16
16
 
17
- desc "Run the specs under spec/models"
17
+ desc "Run the specs under spec/"
18
18
  Spec::Rake::SpecTask.new do |t|
19
19
  t.spec_opts = ['--options', "spec/spec.opts"]
20
20
  t.spec_files = FileList['spec/**/*_spec.rb']
@@ -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/initializers"
44
- assert_generated_file "config/initializers/readme"
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: kennethkalmer-daemon-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5.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-11 00:00:00 -07:00
12
+ date: 2009-05-13 00:00:00 -07:00
13
13
  default_executable: daemon_kit
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/initializers/readme
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