kennethkalmer-daemon-kit 0.1.7.5 → 0.1.7.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/History.txt +21 -0
  2. data/Manifest.txt +16 -6
  3. data/README.rdoc +1 -0
  4. data/Rakefile +2 -1
  5. data/TODO.txt +13 -9
  6. data/app_generators/daemon_kit/daemon_kit_generator.rb +11 -4
  7. data/app_generators/daemon_kit/templates/config/environment.rb +3 -3
  8. data/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
  9. data/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
  10. data/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
  11. data/app_generators/daemon_kit/templates/script/generate +1 -1
  12. data/bin/daemon_kit +1 -2
  13. data/daemon_generators/cron/templates/config/initializers/cron.rb +5 -1
  14. data/daemon_generators/cron/templates/libexec/daemon.rb +6 -2
  15. data/daemon_generators/cucumber/USAGE +11 -0
  16. data/daemon_generators/cucumber/cucumber_generator.rb +38 -0
  17. data/daemon_generators/cucumber/templates/cucumber +8 -0
  18. data/daemon_generators/cucumber/templates/cucumber.rake +13 -0
  19. data/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
  20. data/daemon_generators/cucumber/templates/env.rb +7 -0
  21. data/{rubygems_generators/install_rspec → daemon_generators/rspec}/USAGE +0 -0
  22. data/{rubygems_generators/install_rspec/install_rspec_generator.rb → daemon_generators/rspec/rspec_generator.rb} +7 -9
  23. data/{rubygems_generators/install_rspec → daemon_generators/rspec}/templates/spec.rb +0 -0
  24. data/{rubygems_generators/install_rspec → daemon_generators/rspec}/templates/spec/spec.opts +0 -0
  25. data/{rubygems_generators/install_rspec → daemon_generators/rspec}/templates/spec/spec_helper.rb +0 -1
  26. data/{rubygems_generators/install_rspec → daemon_generators/rspec}/templates/tasks/rspec.rake +0 -0
  27. data/lib/daemon_kit.rb +5 -1
  28. data/lib/daemon_kit/application.rb +5 -1
  29. data/lib/daemon_kit/core_ext/configurable.rb +96 -0
  30. data/lib/daemon_kit/cron.rb +18 -8
  31. data/lib/daemon_kit/cucumber/world.rb +38 -0
  32. data/lib/daemon_kit/em.rb +43 -0
  33. data/lib/daemon_kit/initializer.rb +44 -3
  34. data/lib/daemon_kit/tasks/framework.rake +1 -1
  35. data/spec/configurable_spec.rb +56 -0
  36. metadata +30 -10
data/History.txt CHANGED
@@ -1,3 +1,24 @@
1
+ == 0.1.7.8 2009-06-22
2
+
3
+ * Optional logging of all exceptions when the daemon process dies
4
+ unexpectedly
5
+ * Update generated environment.rb to reflect new backtraces option
6
+
7
+ == 0.1.7.7 2009-06-22
8
+
9
+ * Fixed compatibility with rufus-scheduler-2.0.0 (or newer) in cron
10
+ generator
11
+ * Started central eventmachine reactor management code
12
+ * Now depends on eventmachine
13
+
14
+ == 0.1.7.6 (Not released)
15
+
16
+ * Support for cucumber
17
+ * Fixed issue in daemon_kit:upgrade task
18
+ * Moved rspec generator into new home
19
+ * Removed conflicting rubigen generator, messed with our script directory
20
+ * Fixed bug where environment.rb overwrites some --config values (reported by Josh Owens)
21
+
1
22
  == 0.1.7.5 2009-06-08
2
23
 
3
24
  * New AbstractLogger
data/Manifest.txt CHANGED
@@ -35,6 +35,12 @@ daemon_generators/cron/USAGE
35
35
  daemon_generators/cron/cron_generator.rb
36
36
  daemon_generators/cron/templates/config/initializers/cron.rb
37
37
  daemon_generators/cron/templates/libexec/daemon.rb
38
+ daemon_generators/cucumber/USAGE
39
+ daemon_generators/cucumber/cucumber_generator.rb
40
+ daemon_generators/cucumber/templates/cucumber
41
+ daemon_generators/cucumber/templates/cucumber.rake
42
+ daemon_generators/cucumber/templates/cucumber_environment.rb
43
+ daemon_generators/cucumber/templates/env.rb
38
44
  daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb
39
45
  daemon_generators/deploy_capistrano/templates/Capfile
40
46
  daemon_generators/deploy_capistrano/templates/USAGE
@@ -53,6 +59,12 @@ daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb
53
59
  daemon_generators/nanite_agent/templates/config/nanite.yml
54
60
  daemon_generators/nanite_agent/templates/lib/actors/sample.rb
55
61
  daemon_generators/nanite_agent/templates/libexec/daemon.rb
62
+ daemon_generators/rspec/USAGE
63
+ daemon_generators/rspec/rspec_generator.rb
64
+ daemon_generators/rspec/templates/spec.rb
65
+ daemon_generators/rspec/templates/spec/spec.opts
66
+ daemon_generators/rspec/templates/spec/spec_helper.rb
67
+ daemon_generators/rspec/templates/tasks/rspec.rake
56
68
  lib/daemon_kit.rb
57
69
  lib/daemon_kit/abstract_logger.rb
58
70
  lib/daemon_kit/amqp.rb
@@ -62,9 +74,12 @@ lib/daemon_kit/commands/console.rb
62
74
  lib/daemon_kit/config.rb
63
75
  lib/daemon_kit/console_daemon.rb
64
76
  lib/daemon_kit/core_ext.rb
77
+ lib/daemon_kit/core_ext/configurable.rb
65
78
  lib/daemon_kit/core_ext/string.rb
66
79
  lib/daemon_kit/cron.rb
80
+ lib/daemon_kit/cucumber/world.rb
67
81
  lib/daemon_kit/deployment/capistrano.rb
82
+ lib/daemon_kit/em.rb
68
83
  lib/daemon_kit/error_handlers/base.rb
69
84
  lib/daemon_kit/error_handlers/hoptoad.rb
70
85
  lib/daemon_kit/error_handlers/mail.rb
@@ -80,12 +95,6 @@ lib/daemon_kit/tasks/framework.rake
80
95
  lib/daemon_kit/tasks/god.rake
81
96
  lib/daemon_kit/tasks/log.rake
82
97
  lib/daemon_kit/tasks/monit.rake
83
- rubygems_generators/install_rspec/USAGE
84
- rubygems_generators/install_rspec/install_rspec_generator.rb
85
- rubygems_generators/install_rspec/templates/spec.rb
86
- rubygems_generators/install_rspec/templates/spec/spec.opts
87
- rubygems_generators/install_rspec/templates/spec/spec_helper.rb
88
- rubygems_generators/install_rspec/templates/tasks/rspec.rake
89
98
  script/console
90
99
  script/destroy
91
100
  script/generate
@@ -93,6 +102,7 @@ script/txt2html
93
102
  spec/abstract_logger_spec.rb
94
103
  spec/argument_spec.rb
95
104
  spec/config_spec.rb
105
+ spec/configurable_spec.rb
96
106
  spec/daemon_kit_spec.rb
97
107
  spec/error_handlers_spec.rb
98
108
  spec/fixtures/env.yml
data/README.rdoc CHANGED
@@ -53,6 +53,7 @@ The AMQP generator creates a simple daemon that has all the stub code and config
53
53
  == Requirements
54
54
 
55
55
  * Ruby 1.8.6
56
+ * eventmachine-0.12.8[http://rubyeventmachine.com]
56
57
  * rspec (for writing/running your specs)
57
58
 
58
59
  == Generator Requirements
data/Rakefile CHANGED
@@ -10,7 +10,8 @@ $hoe = Hoe.new('daemon-kit', DaemonKit::VERSION) do |p|
10
10
  p.post_install_message = IO.read( 'PostInstall.txt' ) # TODO remove if post-install message not required
11
11
  p.rubyforge_name = 'kit' # TODO this is default value
12
12
  p.extra_deps = [
13
- ['rubigen', '>= 1.5.2']
13
+ ['rubigen', '>= 1.5.2'],
14
+ ['eventmachine', '>=0.12.8']
14
15
  ]
15
16
  p.extra_dev_deps = [
16
17
  ['newgem', ">= #{::Newgem::VERSION}"]
data/TODO.txt CHANGED
@@ -1,8 +1,19 @@
1
- DaemonKit TODO List
2
- ===================
1
+ = DaemonKit TODO List
3
2
 
4
3
  This is purely a drop in the bucket of what has to come...
5
4
 
5
+ == Eye on 0.2
6
+
7
+ * Support for dropping privileges
8
+ * Support for chroot'ing
9
+ * Altering process names (fully and temporary appending)
10
+ * bleak_house support
11
+ * Support for tweaking REE environment variables prior to launch (bash wrapper)
12
+ * Clustering support (run multiple workers out of same project)
13
+ * Full 1.9 support in the framework
14
+
15
+ == Later
16
+
6
17
  * [IN PROGRESS] Error handling to the degree Rails does
7
18
  * Easy configuration of an ORM of choice, including patching it if needed (ActiveRecord *cough*)
8
19
  * Improved generators for creating skeleton daemons:
@@ -12,9 +23,6 @@ This is purely a drop in the bucket of what has to come...
12
23
  * Queue (SQS, AMQP, etc) pollers
13
24
  * Rake tasks for generating:
14
25
  * Sys-V style init scripts
15
- * Support for dropping privileges
16
- * Support for chroot'ing
17
- * Improved and cleaned up logging, support logrotating (via HUP)
18
26
  * Plenty of docs, seriously a lot of docs
19
27
  * Specs & features, tons of them too
20
28
  * Integration tests for the specific daemons
@@ -25,9 +33,5 @@ This is purely a drop in the bucket of what has to come...
25
33
  * Some activesupport-esque functions until activesupport 3.0 hits the streets
26
34
  * DRY up the following:
27
35
  * Loading configuration files for the daemons
28
- * Altering process names (fully and temporary appending)
29
- * bleak_house support
30
- * Support for tweaking REE environment variables prior to launch (bash wrapper)
31
- * Clustering support (run multiple workers out of same project)
32
36
 
33
37
  * DON'T FORGET 1.9 SUPPORT
@@ -12,6 +12,7 @@ class DaemonKitGenerator < RubiGen::Base
12
12
  attr_reader :daemon_name
13
13
  attr_reader :installer
14
14
  attr_reader :deployer
15
+ attr_reader :cucumber
15
16
 
16
17
  def initialize(runtime_args, runtime_options = {})
17
18
  super
@@ -87,7 +88,10 @@ class DaemonKitGenerator < RubiGen::Base
87
88
  m.directory "tasks"
88
89
 
89
90
  # Tests
90
- m.dependency "install_rspec", [daemon_name], :destination => destination_root, :collision => :force
91
+ m.dependency "rspec", [daemon_name], :destination => destination_root, :collision => :force
92
+ if cucumber
93
+ m.dependency "cucumber", [], :destination => destination_root, :collision => :force
94
+ end
91
95
 
92
96
  # Deployers
93
97
  unless deployer == 'none'
@@ -98,9 +102,6 @@ class DaemonKitGenerator < RubiGen::Base
98
102
  m.directory "log"
99
103
  m.directory "tmp"
100
104
  m.directory "vendor"
101
-
102
- m.dependency "install_rubigen_scripts", [destination_root, 'daemon_kit'],
103
- :shebang => options[:shebang], :collision => :force
104
105
  end
105
106
  end
106
107
 
@@ -136,6 +137,11 @@ EOS
136
137
  options[:deployer] = deploy
137
138
  end
138
139
 
140
+ opts.on("--cucumber",
141
+ "Install cucumber.") do
142
+ options[:cucumber] = true
143
+ end
144
+
139
145
  opts.on("-r", "--ruby=path", String,
140
146
  "Path to the Ruby binary of your choice (otherwise scripts use env, dispatchers current path).",
141
147
  "Default: #{DEFAULT_SHEBANG}") { |x| options[:shebang] = x }
@@ -149,6 +155,7 @@ EOS
149
155
  # @author = options[:author]
150
156
  @installer = options[:installer] || 'default'
151
157
  @deployer = (options[:deployer] || 'none').strip
158
+ @cucumber = options[:cucumber] || false
152
159
  end
153
160
 
154
161
  end
@@ -11,12 +11,12 @@ DaemonKit::Initializer.run do |config|
11
11
  # The name of the daemon as reported by process monitoring tools
12
12
  config.daemon_name = '<%= daemon_name %>'
13
13
 
14
- # Uncomment to allow multiple instances to run
15
- # config.mulitple = true
16
-
17
14
  # Force the daemon to be killed after X seconds from asking it to
18
15
  # config.force_kill_wait = 30
19
16
 
17
+ # Log backraces when a thread/daemon dies (Recommended)
18
+ # config.backtraces = true
19
+
20
20
  # Configure the safety net (see DaemonKit::Safety)
21
21
  # config.safety_net.handler = :mail # (or :hoptoad )
22
22
  # config.safety_net.mail.host = 'localhost'
@@ -0,0 +1,2 @@
1
+ # This is the same context as the environment.rb file, it is only
2
+ # loaded afterwards and only in the development environment
@@ -0,0 +1,2 @@
1
+ # This is the same context as the environment.rb file, it is only
2
+ # loaded afterwards and only in the production environment
@@ -0,0 +1,2 @@
1
+ # This is the same context as the environment.rb file, it is only
2
+ # loaded afterwards and only in the test environment
@@ -10,5 +10,5 @@ end
10
10
  require 'rubigen/scripts/generate'
11
11
 
12
12
  ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
- RubiGen::Base.use_component_sources! [:daemon, :test_unit]
13
+ RubiGen::Base.use_component_sources! [:daemon]
14
14
  RubiGen::Scripts::Generate.new.run(ARGV)
data/bin/daemon_kit CHANGED
@@ -13,7 +13,6 @@ require 'rubigen/scripts/generate'
13
13
  RubiGen::Base.use_application_sources! :rubygems
14
14
  RubiGen::Base.prepend_sources(*[
15
15
  RubiGen::PathSource.new(:app, File.join(File.dirname(__FILE__), "..", "app_generators")),
16
- RubiGen::PathSource.new(:app, File.join(File.dirname(__FILE__), "..", "daemon_generators")),
17
- RubiGen::PathSource.new(:app, File.join(File.dirname(__FILE__), "..", "rubygems_generators"))
16
+ RubiGen::PathSource.new(:app, File.join(File.dirname(__FILE__), "..", "daemon_generators"))
18
17
  ])
19
18
  RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'daemon_kit')
@@ -1,7 +1,11 @@
1
1
  begin
2
- require 'rufus-scheduler'
2
+ require 'rufus/scheduler'
3
3
  rescue LoadError => e
4
4
  $stderr.puts "Missing rufus-scheduler gem. Please run 'gem install rufus-scheduler'."
5
5
  exit 1
6
6
  end
7
7
 
8
+ if Rufus::Scheduler::VERSION < "2.0.0"
9
+ $stderr.puts "Requires rufus-scheduler-2.0.0 or later"
10
+ exit 1
11
+ end
@@ -15,13 +15,17 @@ end
15
15
  # An instance of the scheduler is available through
16
16
  # DaemonKit::Cron.scheduler
17
17
 
18
+ # To make use of the EventMachine-powered scheduler, uncomment the
19
+ # line below *before* adding any schedules.
20
+ # DaemonKit::EM.run
21
+
18
22
  # Some samples to get you going:
19
23
 
20
24
  # Will call #regenerate_monthly_report in 3 days from starting up
21
25
  #DaemonKit::Cron.scheduler.in("3d") do
22
26
  # regenerate_monthly_report()
23
27
  #end
24
- #
28
+ #
25
29
  #DaemonKit::Cron.scheduler.every "10m10s" do
26
30
  # check_score(favourite_team) # every 10 minutes and 10 seconds
27
31
  #end
@@ -35,5 +39,5 @@ DaemonKit::Cron.scheduler.every("1m") do
35
39
  DaemonKit.logger.debug "Scheduled task completed at #{Time.now}"
36
40
  end
37
41
 
38
- # Run our 'cron' daeon
42
+ # Run our 'cron' dameon, suspending the current thread
39
43
  DaemonKit::Cron.run
@@ -0,0 +1,11 @@
1
+ Description:
2
+ Sets up Cucumber in your daemon-kit project. After running this generator you will
3
+ get a new rake task called features.
4
+
5
+ This also generates the necessary files in the features directory.
6
+
7
+ Also see the feature generator, which you can use to generate skeletons
8
+ for new features.
9
+
10
+ Examples:
11
+ `./script/generate cucumber`
@@ -0,0 +1,38 @@
1
+ require 'rbconfig'
2
+ require 'cucumber/version'
3
+
4
+ # This generator bootstraps a Rails project for use with Cucumber
5
+ class CucumberGenerator < RubiGen::Base
6
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
7
+ Config::CONFIG['ruby_install_name'])
8
+
9
+ def manifest
10
+ record do |m|
11
+ m.directory 'features/step_definitions'
12
+ m.template 'cucumber_environment.rb', 'config/environments/cucumber.rb',
13
+ :assigns => { :cucumber_version => ::Cucumber::VERSION::STRING }
14
+
15
+ m.directory 'features/support'
16
+
17
+ #if options[:spork]
18
+ # m.template 'spork_env.rb', 'features/support/env.rb'
19
+ #else
20
+ m.template 'env.rb', 'features/support/env.rb'
21
+ #end
22
+
23
+ m.directory 'tasks'
24
+ m.template 'cucumber.rake', 'tasks/cucumber.rake'
25
+
26
+ m.file 'cucumber', 'script/cucumber', {
27
+ :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang]
28
+ }
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def banner
35
+ "Usage: #{$0} cucumber"
36
+ end
37
+
38
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ load File.expand_path(File.dirname(__FILE__) + "/../vendor/plugins/cucumber/bin/cucumber")
4
+ rescue LoadError => e
5
+ raise unless e.to_s =~ /cucumber/
6
+ require "rubygems"
7
+ load File.join(Gem.bindir, "cucumber")
8
+ end
@@ -0,0 +1,13 @@
1
+ begin
2
+ require 'cucumber/rake/task'
3
+
4
+ Cucumber::Rake::Task.new(:features) do |t|
5
+ t.fork = true
6
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
7
+ end
8
+ rescue LoadError
9
+ desc 'Cucumber rake task not available'
10
+ task :features do
11
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ gem "cucumber", ">=<%= cucumber_version %>"
2
+ gem "rspec", ">=1.2.6"
@@ -0,0 +1,7 @@
1
+ # Sets up the DaemonKit environment for Cucumber
2
+ ENV["DAEMON_ENV"] ||= "cucumber"
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
4
+ require 'daemon_kit/cucumber/world'
5
+
6
+ # Comment out the next line if you don't want Cucumber Unicode support
7
+ require 'cucumber/formatter/unicode'
@@ -1,10 +1,8 @@
1
1
 
2
- class InstallRspecGenerator < RubiGen::Base
3
-
4
- default_options :author => nil
5
-
2
+ class RspecGenerator < RubiGen::Base
3
+
6
4
  attr_reader :gem_name, :module_name
7
-
5
+
8
6
  def initialize(runtime_args, runtime_options = {})
9
7
  super
10
8
  @destination_root = File.expand_path(destination_root)
@@ -20,7 +18,7 @@ class InstallRspecGenerator < RubiGen::Base
20
18
  m.directory 'tasks'
21
19
 
22
20
  m.template 'spec.rb', "spec/#{gem_name}_spec.rb"
23
-
21
+
24
22
  m.template_copy_each %w( spec.opts spec_helper.rb ), 'spec'
25
23
  m.file_copy_each %w( rspec.rake ), 'tasks'
26
24
  end
@@ -29,7 +27,7 @@ class InstallRspecGenerator < RubiGen::Base
29
27
  protected
30
28
  def banner
31
29
  <<-EOS
32
- Install rspec BDD testing support.
30
+ Install rspec BDD testing support.
33
31
 
34
32
  Includes a rake task (tasks/rspec.rake) to be loaded by the root Rakefile,
35
33
  which provides a "spec" task.
@@ -47,11 +45,11 @@ EOS
47
45
  # "Some comment about this option",
48
46
  # "Default: none") { |x| options[:author] = x }
49
47
  end
50
-
48
+
51
49
  def extract_options
52
50
  # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
53
51
  # Templates can access these value via the attr_reader-generated methods, but not the
54
52
  # raw instance variable value.
55
53
  # @author = options[:author]
56
54
  end
57
- end
55
+ end
@@ -8,7 +8,6 @@ end
8
8
 
9
9
  require File.dirname(__FILE__) + '/../config/environment'
10
10
  DaemonKit::Application.running!
11
- require '<%= gem_name %>'
12
11
 
13
12
  Spec::Runner.configure do |config|
14
13
  # == Mock Framework
data/lib/daemon_kit.rb CHANGED
@@ -1,13 +1,15 @@
1
1
  # TODO: Strip this out eventually so we can run without rubygems
2
2
  require 'rubygems'
3
3
 
4
+ require 'eventmachine'
5
+
4
6
  require File.dirname(__FILE__) + '/daemon_kit/core_ext'
5
7
 
6
8
  $:.unshift( File.dirname(__FILE__).to_absolute_path ) unless
7
9
  $:.include?( File.dirname(__FILE__).to_absolute_path )
8
10
 
9
11
  module DaemonKit
10
- VERSION = '0.1.7.5'
12
+ VERSION = '0.1.7.7'
11
13
 
12
14
  autoload :Initializer, 'daemon_kit/initializer'
13
15
  autoload :Application, 'daemon_kit/application'
@@ -16,6 +18,8 @@ module DaemonKit
16
18
  autoload :Safety, 'daemon_kit/safety'
17
19
  autoload :PidFile, 'daemon_kit/pid_file'
18
20
  autoload :AbstractLogger, 'daemon_kit/abstract_logger'
21
+ autoload :EM, 'daemon_kit/em'
22
+ autoload :Configurable, 'daemon_kit/core_ext/configurable'
19
23
 
20
24
  autoload :Cron, 'daemon_kit/cron'
21
25
  autoload :Jabber, 'daemon_kit/jabber'
@@ -79,7 +79,11 @@ module DaemonKit
79
79
  end
80
80
  end
81
81
 
82
- @pid_file.cleanup
82
+ if @pid_file.running?
83
+ puts "Process still running, leaving pidfile behind! Consider using configuration.force_kill_wait."
84
+ else
85
+ @pid_file.cleanup
86
+ end
83
87
  end
84
88
 
85
89
  # Call this from inside a daemonized process to complete the
@@ -0,0 +1,96 @@
1
+ module DaemonKit
2
+
3
+ # Provide some advanced helpers for managing access to instance variables.
4
+ module Configurable
5
+
6
+ def self.included(base) #:nodoc:
7
+ base.class_eval <<-EOF
8
+ @configurables = {}
9
+ @configurable_defaults = {}
10
+
11
+ class << self
12
+ attr_reader :configurables, :configurable_defaults
13
+ end
14
+ EOF
15
+
16
+ base.extend( ClassMethods )
17
+ base.send( :include, InstanceMethods )
18
+ end
19
+
20
+ module ClassMethods
21
+
22
+ # Create a configurable value on any instance, which can contain
23
+ # a default value, and/or be locked.
24
+ #
25
+ # Create a standard getter/setter without a default value
26
+ #
27
+ # configurable :foo
28
+ #
29
+ # Create a getter/setter with a default value
30
+ #
31
+ # configurable :foo, true
32
+ #
33
+ # The final argument can be an options hash, which currently
34
+ # respects only one key: +locked+ (false by default). Locking a
35
+ # configurable means the value can only be set once by the
36
+ # setter method.
37
+ #
38
+ # configurable :foo, :locked => true
39
+ #
40
+ # As long as the getter method (+foo+) returns nil, the standard
41
+ # setter method will work. As soon as the getter returns a
42
+ # non-nil value the setter won't set a new value. To set a new
43
+ # value you'll have to explicitly use the #set instance method.
44
+ def configurable( name, *args )
45
+ opts = args.last.is_a?( Hash ) ? args.pop : {}
46
+ opts = { :locked => false }.merge( opts )
47
+
48
+ default = args.size <= 1 ? args.pop : args
49
+
50
+ name = name.to_sym
51
+
52
+ self.configurables[ name ] = opts
53
+ self.configurable_defaults[ name ] = default
54
+
55
+ class_eval( <<-EOF, __FILE__, __LINE__ )
56
+ def #{name} # def foo
57
+ if _configurables[:#{name}].nil? # if _configurables[:foo].nil?
58
+ self.class.configurable_defaults[:#{name}] # self.class.configurable_defaults[:foo]
59
+ else # else
60
+ _configurables[:#{name}] # _configurables[:foo]
61
+ end # end
62
+ end #
63
+
64
+ def #{name}=( value ) # def foo=( value )
65
+ if #{name}.nil? || # if foo.nil? ||
66
+ !self.class.configurables[:#{name}][:locked] # !self.class.configurables[:foo][:locked]
67
+ #
68
+ _configurables[:#{name}] = value # _configurables[:foo] = value
69
+ end # end
70
+ end # end
71
+ EOF
72
+ end
73
+
74
+ end
75
+
76
+ module InstanceMethods
77
+
78
+ # Force the value of a configurable to be set without any
79
+ # respect for it's locked status.
80
+ def set( name, value )
81
+ name = name.to_sym
82
+
83
+ if self.class.configurables.has_key?( name )
84
+ _configurables[ name ] = value
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def _configurables
91
+ @_configurables ||= {}
92
+ end
93
+
94
+ end
95
+ end
96
+ end
@@ -1,15 +1,22 @@
1
1
  module DaemonKit
2
-
2
+
3
3
  # Thin wrapper around rufus-scheduler gem, specifically designed to ease
4
4
  # configuration of a scheduler and provide some added simplicity.
5
+ #
6
+ # For more information on rufus-scheduler, please visit the RDoc's
7
+ # at http://rufus.rubyforge.org/rufus-scheduler/
8
+ #
9
+ # To use the evented scheduler, call #DaemonKit::EM.run prior to
10
+ # setting up your first schedule.
5
11
  class Cron
6
12
 
7
- @@instance = nil
13
+ @instance = nil
8
14
 
9
15
  attr_reader :scheduler
10
-
16
+
11
17
  class << self
12
-
18
+
19
+ # Access to the scheduler instance
13
20
  def instance
14
21
  @instance ||= new
15
22
  end
@@ -17,16 +24,19 @@ module DaemonKit
17
24
  def scheduler
18
25
  instance.scheduler
19
26
  end
20
-
27
+
21
28
  private :new
22
29
 
30
+ # Once the scheduler has been configured, call #run to block the
31
+ # current thread and keep the process alive for the scheduled
32
+ # tasks to run
23
33
  def run
24
34
  DaemonKit.logger.info "Starting rufus-scheduler"
25
35
 
26
- begin
36
+ if instance.is_a?( Rufus::Scheduler::PlainScheduler )
27
37
  instance.scheduler.join
28
- rescue Interrupt
29
- DaemonKit.logger.warn "Scheduler interrupted"
38
+ else
39
+ Thread.stop
30
40
  end
31
41
  end
32
42
  end
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Based on code from Brian Takita, Yurii Rashkovskii, Ben Mabey and Aslak Hellesøy
3
+ # Adapted by Kenneth Kalmer for daemon-kit
4
+
5
+ begin
6
+ require 'test/unit/testresult'
7
+ rescue LoadError => e
8
+ e.message << "\nYou must gem install test-unit. For more info see https://rspec.lighthouseapp.com/projects/16211/tickets/292"
9
+ raise e
10
+ end
11
+
12
+ # So that Test::Unit doesn't launch at the end - makes it think it has already been run.
13
+ Test::Unit.run = true if Test::Unit.respond_to?(:run=)
14
+
15
+ $__cucumber_toplevel = self
16
+
17
+ module DaemonKit
18
+ module Cucumber
19
+ # All scenarios will execute in the context of a new instance of World.
20
+ class World
21
+ def initialize #:nodoc:
22
+ @_result = Test::Unit::TestResult.new
23
+ end
24
+ end
25
+
26
+ $__cucumber_toplevel.Before do
27
+ # Placeholder
28
+ end
29
+
30
+ $__cucumber_toplevel.After do
31
+ # Placeholder
32
+ end
33
+ end
34
+ end
35
+
36
+ World do
37
+ DaemonKit::Cucumber::World.new
38
+ end
@@ -0,0 +1,43 @@
1
+ module DaemonKit
2
+
3
+ # EventMachine forms a critical part of the daemon-kit toolset, and
4
+ # especially of daemon process developers.
5
+ #
6
+ # This class abstracts away the difficulties of managing multiple
7
+ # libraries that all utilize the event reactor.
8
+ class EM
9
+
10
+ class << self
11
+
12
+ # Start a reactor, just like classical EM.run. If the block is
13
+ # provided, the method will block and call the provided block
14
+ # argument inside the running reactor. If the block argument is
15
+ # not provided the reactor will be started in a separate thread
16
+ # and the program will continue to run after the method. All the
17
+ # signal traps are configured to shutdown the reactor when the
18
+ # daemon exists.
19
+ def run(&block)
20
+ if ::EM.reactor_running?
21
+ DaemonKit.logger.warn "EventMachine reactor already running"
22
+ block.call if block_given?
23
+
24
+ else
25
+ if block_given?
26
+ ::EM.run { block.call }
27
+ else
28
+ Thread.main[:_dk_reactor] = Thread.new { EM.run {} }
29
+ DaemonKit.trap( 'INT' ) { DaemonKit::EM.stop }
30
+ DaemonKit.trap( 'TERM' ) { DaemonKit::EM.stop }
31
+ end
32
+ end
33
+ end
34
+
35
+ # Stop the reactor
36
+ def stop
37
+ ::EM.stop_event_loop if ::EM.reactor_running?
38
+ Thread.main[:_dk_reactor].join
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -61,6 +61,10 @@ module DaemonKit
61
61
  end
62
62
 
63
63
  def self.shutdown
64
+ DaemonKit.logger.info "Running shutdown hooks"
65
+
66
+ log_exceptions if DaemonKit.configuration.backtraces
67
+
64
68
  DaemonKit.logger.warn "Shutting down #{DaemonKit.configuration.daemon_name}"
65
69
  exit
66
70
  end
@@ -85,6 +89,7 @@ module DaemonKit
85
89
 
86
90
  include_core_lib
87
91
  load_postdaemonize_configs
92
+ configure_backtraces
88
93
 
89
94
  set_process_name
90
95
 
@@ -160,6 +165,7 @@ module DaemonKit
160
165
  term_proc = Proc.new { DaemonKit::Initializer.shutdown }
161
166
  configuration.trap( 'INT', term_proc )
162
167
  configuration.trap( 'TERM', term_proc )
168
+ at_exit { DaemonKit::Initializer.shutdown }
163
169
  end
164
170
 
165
171
  def include_core_lib
@@ -168,13 +174,45 @@ module DaemonKit
168
174
  end
169
175
  end
170
176
 
177
+ def configure_backtraces
178
+ Thread.abort_on_exception = configuration.backtraces
179
+ end
180
+
171
181
  def set_process_name
172
182
  $0 = configuration.daemon_name
173
183
  end
184
+
185
+ def self.log_exceptions
186
+ trace_file = File.join( DaemonKit.root, "backtrace-#{Time.now.strftime('%Y%m%d%H%M%S')}-#{Process.pid}.log" )
187
+ trace_log = Logger.new( trace_file )
188
+
189
+ # Find the last exception
190
+ e = nil
191
+ ObjectSpace.each_object {|o|
192
+ if ::Exception === o
193
+ e = o
194
+ end
195
+ }
196
+
197
+ trace_log.info "*** Below you'll find the most recent exception thrown, this will likely (but not certainly) be the exception that made #{DaemonKit.configuration.daemon_name} exit abnormally ***"
198
+ trace_log.error e
199
+
200
+ trace_log.info "*** Below you'll find all the exception objects in memory, some of them may have been thrown in your application, others may just be in memory because they are standard exceptions ***"
201
+ ObjectSpace.each_object {|o|
202
+ if ::Exception === o
203
+ trace_log.error o
204
+ end
205
+ }
206
+
207
+ trace_log.close
208
+ end
174
209
  end
175
210
 
176
211
  # Holds our various configuration values
177
212
  class Configuration
213
+
214
+ include Configurable
215
+
178
216
  # Root to the daemon
179
217
  attr_reader :root_path
180
218
 
@@ -188,7 +226,7 @@ module DaemonKit
188
226
  attr_accessor :log_level
189
227
 
190
228
  # Path to the log file, defaults to 'log/<environment>.log'
191
- attr_accessor :log_path
229
+ configurable :log_path
192
230
 
193
231
  # Duplicate log data to stdout
194
232
  attr_accessor :log_stdout
@@ -197,10 +235,13 @@ module DaemonKit
197
235
  attr_accessor :pid_file
198
236
 
199
237
  # The application name
200
- attr_accessor :daemon_name
238
+ configurable :daemon_name, :locked => true
201
239
 
202
240
  # Use the force kill patch? Give the number of seconds
203
- attr_accessor :force_kill_wait
241
+ configurable :force_kill_wait
242
+
243
+ # Should be log backtraces
244
+ configurable :backtraces, false
204
245
 
205
246
  # Collection of signal traps
206
247
  attr_reader :signal_traps
@@ -87,7 +87,7 @@ namespace :daemon_kit do
87
87
  namespace :upgrade do
88
88
  # Upgrade the initializers
89
89
  task :initializers do
90
- copy_framework_template( 'config/boot.rb', 'config/boot.rb' )
90
+ copy_framework_template( 'config', 'boot.rb' )
91
91
 
92
92
  if File.directory?( File.join(DaemonKit.root, 'config', 'initializers') )
93
93
  mv File.join(DaemonKit.root, 'config', 'initializers'), File.join(DAEMON_ROOT, 'config', 'pre-daemonize')
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class FooConfig
4
+ include DaemonKit::Configurable
5
+
6
+ configurable :has_default, true
7
+ configurable :no_default
8
+ configurable :has_lock, :locked => true
9
+ end
10
+
11
+ describe DaemonKit::Configurable do
12
+
13
+ before(:each) do
14
+ @foo = FooConfig.new
15
+ end
16
+
17
+ it "should support default values" do
18
+ lambda {
19
+ @foo.has_default.should be_true
20
+ }.should_not raise_error( NoMethodError )
21
+ end
22
+
23
+ it "should support overwriting unlocked defaults" do
24
+ lambda {
25
+ @foo.has_default = false
26
+ @foo.has_default.should be_false
27
+ }.should_not raise_error
28
+ end
29
+
30
+ it "should support no default values" do
31
+ lambda {
32
+ @foo.no_default.should be_nil
33
+ }.should_not raise_error( NoMethodError )
34
+ end
35
+
36
+ it "should allow setting locked values once" do
37
+ lambda {
38
+ @foo.has_lock = 1
39
+ @foo.has_lock.should == 1
40
+
41
+ @foo.has_lock = 2
42
+ @foo.has_lock.should == 1
43
+ }.should_not raise_error
44
+ end
45
+
46
+ it "should allow bypassing the lock explicitly" do
47
+ lambda {
48
+ @foo.has_lock = 1
49
+ @foo.has_lock.should == 1
50
+
51
+ @foo.set(:has_lock, 2)
52
+ @foo.has_lock.should == 2
53
+ }.should_not raise_error
54
+ end
55
+
56
+ end
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.7.5
4
+ version: 0.1.7.7
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-06-08 00:00:00 -07:00
12
+ date: 2009-06-22 00:00:00 -07:00
13
13
  default_executable: daemon_kit
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,6 +22,16 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 1.5.2
24
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: eventmachine
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.12.8
34
+ version:
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: newgem
27
37
  type: :development
@@ -96,6 +106,12 @@ files:
96
106
  - daemon_generators/cron/cron_generator.rb
97
107
  - daemon_generators/cron/templates/config/initializers/cron.rb
98
108
  - daemon_generators/cron/templates/libexec/daemon.rb
109
+ - daemon_generators/cucumber/USAGE
110
+ - daemon_generators/cucumber/cucumber_generator.rb
111
+ - daemon_generators/cucumber/templates/cucumber
112
+ - daemon_generators/cucumber/templates/cucumber.rake
113
+ - daemon_generators/cucumber/templates/cucumber_environment.rb
114
+ - daemon_generators/cucumber/templates/env.rb
99
115
  - daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb
100
116
  - daemon_generators/deploy_capistrano/templates/Capfile
101
117
  - daemon_generators/deploy_capistrano/templates/USAGE
@@ -114,6 +130,12 @@ files:
114
130
  - daemon_generators/nanite_agent/templates/config/nanite.yml
115
131
  - daemon_generators/nanite_agent/templates/lib/actors/sample.rb
116
132
  - daemon_generators/nanite_agent/templates/libexec/daemon.rb
133
+ - daemon_generators/rspec/USAGE
134
+ - daemon_generators/rspec/rspec_generator.rb
135
+ - daemon_generators/rspec/templates/spec.rb
136
+ - daemon_generators/rspec/templates/spec/spec.opts
137
+ - daemon_generators/rspec/templates/spec/spec_helper.rb
138
+ - daemon_generators/rspec/templates/tasks/rspec.rake
117
139
  - lib/daemon_kit.rb
118
140
  - lib/daemon_kit/abstract_logger.rb
119
141
  - lib/daemon_kit/amqp.rb
@@ -123,9 +145,12 @@ files:
123
145
  - lib/daemon_kit/config.rb
124
146
  - lib/daemon_kit/console_daemon.rb
125
147
  - lib/daemon_kit/core_ext.rb
148
+ - lib/daemon_kit/core_ext/configurable.rb
126
149
  - lib/daemon_kit/core_ext/string.rb
127
150
  - lib/daemon_kit/cron.rb
151
+ - lib/daemon_kit/cucumber/world.rb
128
152
  - lib/daemon_kit/deployment/capistrano.rb
153
+ - lib/daemon_kit/em.rb
129
154
  - lib/daemon_kit/error_handlers/base.rb
130
155
  - lib/daemon_kit/error_handlers/hoptoad.rb
131
156
  - lib/daemon_kit/error_handlers/mail.rb
@@ -141,12 +166,6 @@ files:
141
166
  - lib/daemon_kit/tasks/god.rake
142
167
  - lib/daemon_kit/tasks/log.rake
143
168
  - lib/daemon_kit/tasks/monit.rake
144
- - rubygems_generators/install_rspec/USAGE
145
- - rubygems_generators/install_rspec/install_rspec_generator.rb
146
- - rubygems_generators/install_rspec/templates/spec.rb
147
- - rubygems_generators/install_rspec/templates/spec/spec.opts
148
- - rubygems_generators/install_rspec/templates/spec/spec_helper.rb
149
- - rubygems_generators/install_rspec/templates/tasks/rspec.rake
150
169
  - script/console
151
170
  - script/destroy
152
171
  - script/generate
@@ -154,6 +173,7 @@ files:
154
173
  - spec/abstract_logger_spec.rb
155
174
  - spec/argument_spec.rb
156
175
  - spec/config_spec.rb
176
+ - spec/configurable_spec.rb
157
177
  - spec/daemon_kit_spec.rb
158
178
  - spec/error_handlers_spec.rb
159
179
  - spec/fixtures/env.yml
@@ -236,11 +256,11 @@ specification_version: 2
236
256
  summary: Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code.
237
257
  test_files:
238
258
  - test/test_generator_helper.rb
239
- - test/test_jabber_generator.rb
240
259
  - test/test_cron_generator.rb
241
- - test/test_amqp_generator.rb
242
260
  - test/test_nanite_agent_generator.rb
243
261
  - test/test_daemon_kit_config.rb
244
262
  - test/test_helper.rb
263
+ - test/test_amqp_generator.rb
245
264
  - test/test_daemon-kit_generator.rb
246
265
  - test/test_deploy_capistrano_generator.rb
266
+ - test/test_jabber_generator.rb