daemonz 0.3.0 → 0.3.1

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/README.textile CHANGED
@@ -4,9 +4,14 @@ bq. Automatically starts and stops the daemons in a Rails application.
4
4
 
5
5
  h2. Installation
6
6
 
7
- Install with:
7
+ Add the following entry to your Gemfile:
8
8
  <pre>
9
- script/plugin install git://github.com/costan/daemonz.git
9
+ gem 'daemonz'
10
+ </pre>
11
+
12
+ After running <code>bundle install</code> generate the default configuration:
13
+ <pre>
14
+ rails g daemonz:config
10
15
  </pre>
11
16
 
12
17
  You don't need to do anything in your code for daemonz to work. It will start
@@ -31,7 +36,7 @@ The scaffolded code includes the configuration file, a daemon skeleton using the
31
36
  <code>simple-daemon</code> gem, and an integration test skeleton.
32
37
 
33
38
  <pre>
34
- script/generate daemon YourDaemonName
39
+ rails g daemon YourDaemonName
35
40
  </pre>
36
41
 
37
42
  h2. Testing
data/Rakefile CHANGED
@@ -1,22 +1,19 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
-
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the daemonz plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = true
13
- end
14
-
15
- desc 'Generate documentation for the daemonz plugin.'
16
- Rake::RDocTask.new(:rdoc) do |rdoc|
17
- rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = 'Daemonz'
19
- rdoc.options << '--line-numbers' << '--inline-source'
20
- rdoc.rdoc_files.include('README')
21
- rdoc.rdoc_files.include('lib/**/*.rb')
1
+ require "rake"
2
+
3
+ begin
4
+ require "jeweler"
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "daemonz"
7
+ gem.summary = "Automatically starts and stops the daemons in a Rails application"
8
+ gem.email = "victor@costan.us"
9
+ gem.homepage = "http://github.com/costan/daemonz"
10
+ gem.authors = ["Victor Costan"]
11
+ gem.files = Dir["*", "{lib}/**/*"]
12
+ gem.add_dependency 'simple-daemon'
13
+ gem.add_dependency 'zerg_support'
14
+ end
15
+
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
22
19
  end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.1
data/daemonz.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{daemonz}
8
- s.version = "0.3.0"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Victor Costan"]
@@ -18,16 +18,27 @@ Gem::Specification.new do |s|
18
18
  "MIT-LICENSE",
19
19
  "README.textile",
20
20
  "Rakefile",
21
+ "VERSION",
21
22
  "config_template.yml",
22
23
  "daemonz.gemspec",
23
24
  "init.rb",
24
25
  "lib/daemonz.rb",
25
26
  "lib/daemonz/config.rb",
27
+ "lib/daemonz/generators/config/config_generator.rb",
28
+ "lib/daemonz/generators/config/templates/config.yml",
29
+ "lib/daemonz/generators/config/templates/prepackaged/ferret.yml",
30
+ "lib/daemonz/generators/config/templates/prepackaged/starling.yml",
31
+ "lib/daemonz/generators/daemon/daemon_generator.rb",
32
+ "lib/daemonz/generators/daemon/templates/config.yml",
33
+ "lib/daemonz/generators/daemon/templates/daemon.rb.erb",
34
+ "lib/daemonz/generators/daemon/templates/integration_test.rb.erb",
26
35
  "lib/daemonz/killer.rb",
27
36
  "lib/daemonz/logging.rb",
28
37
  "lib/daemonz/manage.rb",
29
38
  "lib/daemonz/master.rb",
30
- "lib/daemonz/process.rb"
39
+ "lib/daemonz/process.rb",
40
+ "lib/daemonz/railtie.rb",
41
+ "lib/daemonz/tasks/daemonz_tasks.rake"
31
42
  ]
32
43
  s.homepage = %q{http://github.com/costan/daemonz}
33
44
  s.rdoc_options = ["--charset=UTF-8"]
@@ -17,7 +17,7 @@ module Daemonz
17
17
 
18
18
  def self.disabled_without_cache!
19
19
  return true if config[:disabled]
20
- return true if config[:disabled_in].include? RAILS_ENV
20
+ return true if config[:disabled_in].include? Rails.root
21
21
  config[:disabled_for].any? do |suffix|
22
22
  suffix == $0[-suffix.length, suffix.length]
23
23
  end
@@ -27,7 +27,7 @@ module Daemonz
27
27
  def self.configure(config_file, options = {})
28
28
  load_configuration config_file
29
29
 
30
- config[:root_path] ||= RAILS_ROOT
30
+ config[:root_path] ||= Rails.root
31
31
  if options[:force_enabled]
32
32
  config[:disabled] = false
33
33
  config[:disabled_for] = []
@@ -38,7 +38,7 @@ module Daemonz
38
38
  config[:disabled_in] ||= ['test']
39
39
  end
40
40
  config[:disabled] = false if config[:disabled] == 'false'
41
- config[:master_file] ||= File.join RAILS_ROOT, "tmp", "pids", "daemonz.master.pid"
41
+ config[:master_file] ||= Rails.root.join "tmp", "pids", "daemonz.master.pid"
42
42
 
43
43
  config[:logger] &&= options[:override_logger]
44
44
  self.configure_logger
@@ -77,7 +77,7 @@ module Daemonz
77
77
  end
78
78
  else
79
79
  logger.warn "Daemonz configuration not found - #{config_file}"
80
- @config = {}
80
+ @config = { :disabled => true }
81
81
  end
82
82
  end
83
83
 
@@ -0,0 +1,21 @@
1
+ # :nodoc: namespace
2
+ module Daemonz
3
+ # :nodoc: namespace
4
+ module Generators
5
+
6
+ class ConfigGenerator < Rails::Generators::Base
7
+ def self.source_root
8
+ @source_root ||= File.expand_path 'templates', File.dirname(__FILE__)
9
+ end
10
+
11
+ def create_configuration
12
+ copy_file 'config.yml', 'config/daemonz.yml'
13
+
14
+ empty_directory 'config/daemonz'
15
+ copy_file 'prepackaged/ferret.yml', 'config/daemonz/ferret.yml'
16
+ copy_file 'prepackaged/starling.yml', 'config/daemonz/starling.yml'
17
+ end
18
+ end # class Daemonz::Generators::ConfigGenerator
19
+
20
+ end # namespace Daemonz::Generators
21
+ end # namespace Daemonz
@@ -0,0 +1,36 @@
1
+ # Configuration file for the daemonz plugin.
2
+
3
+ ---
4
+ :daemons:
5
+ # Daemon configurations placed here will be read as if they were in a file in
6
+ # config/daemonz. This is more maintainable if you only have one daemon.
7
+
8
+ # The base path for daemon binaries specified in binary, start_binary and
9
+ # stop_binary.
10
+ :root_path: <%= Rails.root %>
11
+
12
+ # Where daemonz should log - set to stdout, stderr, or rails.
13
+ :logger: stdout
14
+
15
+ # Set to true to completely disable daemonz, and not load any plugins.
16
+ :disabled: false
17
+
18
+ # daemonz is loaded every time the Rails framework is loaded. Sometimes
19
+ # (e.g. when performing migrations) daemons aren't required, so we shouldn't
20
+ # have to wait for the few seconds it takes to start / stop daemons.
21
+
22
+ # Daemons will not be started / stopped when the name of the binary that's
23
+ # loading Rails ($0) is one of the following.
24
+ :disabled_for:
25
+ - 'rake'
26
+ - 'script/generate'
27
+ - 'script/destroy'
28
+ - 'script/plugin'
29
+ # Assuming you don't want to wait for daemons to start most of the times when
30
+ # you pull up a console. You can always start / stop them up by hand with
31
+ # rake daemons:start / rake daemons:stop, or you can remove the line below.
32
+ - 'irb'
33
+
34
+ # Daemons will not be started for the following environments.
35
+ :disabled_in:
36
+ - 'test'
@@ -0,0 +1,38 @@
1
+ # Daemonz example: configuration for ferret.
2
+ #
3
+ # daemonz starts the daemons according to the alphabetic order of their
4
+ # configuration file names. start_order can be used to override this order.
5
+ # Daemons will be stopped in the reverse order of their starting order.
6
+ #
7
+ # daemonz likes to ensure that multiple instances of a daemon don't run at the
8
+ # same time, as this can be fatal for daemons with on-disk state, like ferret.
9
+ # So daemonz ensures that a daemon is dead before starting it, and right after
10
+ # stopping it. This is achieved using the following means:
11
+ # * Stop commands: first, daemonz uses the stop command supplied in the daemon
12
+ # configuration
13
+ # * PID files: if the daemon has .pid files, daemonz tries to read the file
14
+ # and find the corresponding processes, then tree-kills them
15
+ # * Process table: if possible, daemonz dumps the process table, looks for the
16
+ # processes that look like the daemon, and tree-kills them
17
+ # * Pattern matching: processes whose command lines have the same arguments as
18
+ # those given to daemon "look like" that daemon
19
+ # * Tree killing: a daemon is killed by killing its main process, together
20
+ # with all processes descending from that process; a process
21
+ # is first sent SIGTERM and, if it's still alive after a
22
+ # couple of seconds, it's sent a SIGKILL
23
+
24
+ ---
25
+ ferret:
26
+ # Ferret uses different binaries to be started and stopped.
27
+ :start_binary: script/ferret_server
28
+ :stop_binary: script/ferret_server
29
+ # The arguments to be given to the start and stop commands.
30
+ # Note that this file is processed with Erb, like your views.
31
+ :start_args: -e <%= Rails.env %> start
32
+ :stop_args: -e <%= Rails.env %> stop
33
+ # Time to wait after sending the stop command, before killing the daemon.
34
+ :delay_before_kill: 0.35
35
+ # Pattern for the PID file(s) used by the daemon.
36
+ :pids: tmp/pids/ferret*.pid
37
+ # daemonz will ignore this daemon configuration when this flag is true
38
+ :disabled: true
@@ -0,0 +1,43 @@
1
+ # Daemonz example: configuration for running starling.
2
+ #
3
+ # daemonz starts the daemons according to the alphabetic order of their
4
+ # configuration file names. start_order can be used to override this order.
5
+ # Daemons will be stopped in the reverse order of their starting order.
6
+ #
7
+ # daemonz likes to ensure that multiple instances of a daemon don't run at the
8
+ # same time, as this can be fatal for daemons with on-disk state, like ferret.
9
+ # So daemonz ensures that a daemon is dead before starting it, and right after
10
+ # stopping it. This is achieved using the following means:
11
+ # * Stop commands: first, daemonz uses the stop command supplied in the daemon
12
+ # configuration
13
+ # * PID files: if the daemon has .pid files, daemonz tries to read the file
14
+ # and find the corresponding processes, then tree-kills them
15
+ # * Process table: if possible, daemonz dumps the process table, looks for the
16
+ # processes that look like the daemon, and tree-kills them
17
+ # * Pattern matching: processes whose command lines have the same arguments as
18
+ # those given to daemon "look like" that daemon
19
+ # * Tree killing: a daemon is killed by killing its main process, together
20
+ # with all processes descending from that process; a process
21
+ # is first sent SIGTERM and, if it's still alive after a
22
+ # couple of seconds, it's sent a SIGKILL
23
+
24
+ ---
25
+ starling:
26
+ # The same binary is used to start and stop starling.
27
+ :binary: starling
28
+ # The binary name will not be merged with root_path.
29
+ :absolute_binary: true
30
+ :start_args: -d -h 127.0.0.1 -p 16020 -P <%= Rails.root.join 'tmp', 'pids', 'starling.pid' %> -q <%= Rails.root.join 'tmp' %> -L <%= Rails.root.join 'log', 'starling.log' %>
31
+ # No arguments are needed to stop starling.
32
+ :stop_args: ''
33
+ # Pattern for the PID file(s) used by the daemon.
34
+ :pids: tmp/pids/starling*.pid
35
+ # Override for the patterns used to identify the daemon's processes.
36
+ :kill_patterns: <%= Rails.root.join 'log', 'starling.log' %>
37
+ # Time to wait after sending the stop command, before killing the daemon.
38
+ :delay_before_kill: 0.2
39
+ # Override the daemon startup order. Starling consumer daemons should have
40
+ # their start_order set to 2, so starling is running when they start.
41
+ :start_order: 1
42
+ # daemonz will ignore this daemon configuration when this flag is true
43
+ :disabled: true
@@ -0,0 +1,24 @@
1
+ # :nodoc: namespace
2
+ module Daemonz
3
+ # :nodoc: namespace
4
+ module Generators
5
+
6
+ class DaemonGenerator < Rails::Generators::NamedBase
7
+ def self.source_root
8
+ @source_root ||= File.expand_path 'templates', File.dirname(__FILE__)
9
+ end
10
+
11
+ def create_harness
12
+ empty_directory 'config/daemonz'
13
+ template "config.yml", "config/daemonz/#{file_name}.yml"
14
+
15
+ empty_directory 'script/background'
16
+ template 'daemon.rb.erb', "script/background/#{file_name}.rb"
17
+
18
+ empty_directory 'test/integration'
19
+ template 'integration_test.rb.erb', "test/integration/#{file_name}_test.rb"
20
+ end
21
+ end # class Daemon::Generators::DaemonGenerator
22
+
23
+ end # namespace Daemon::Generators
24
+ end # namespace Daemon
@@ -0,0 +1,39 @@
1
+ # Automatically generated daemon configuration for <%= file_name %>.
2
+ #
3
+ # daemonz starts the daemons according to the alphabetic order of their
4
+ # configuration file names. start_order can be used to override this order.
5
+ # Daemons will be stopped in the reverse order of their starting order.
6
+ #
7
+ # daemonz likes to ensure that multiple instances of a daemon don't run at the
8
+ # same time, as this can be fatal for daemons with on-disk state, like ferret.
9
+ # So daemonz ensures that a daemon is dead before starting it, and right after
10
+ # stopping it. This is achieved using the following means:
11
+ # * Stop commands: first, daemonz uses the stop command supplied in the daemon
12
+ # configuration
13
+ # * PID files: if the daemon has .pid files, daemonz tries to read the file
14
+ # and find the corresponding processes, then tree-kills them
15
+ # * Process table: if possible, daemonz dumps the process table, looks for the
16
+ # processes that look like the daemon, and tree-kills them
17
+ # * Pattern matching: processes whose command lines have the same arguments as
18
+ # those given to daemon "look like" that daemon
19
+ # * Tree killing: a daemon is killed by killing its main process, together
20
+ # with all processes descending from that process; a process
21
+ # is first sent SIGTERM and, if it's still alive after a
22
+ # couple of seconds, it's sent a SIGKILL
23
+
24
+ ---
25
+ <%= file_name %>:
26
+ # Pattern for the PID file(s) used by the daemon.
27
+ :pids: tmp/<%= class_name %>.pid
28
+ # The same binary is used to start and stop <% file_name %>.
29
+ :binary: script/background/<%= file_name %>.rb
30
+ # The arguments to be given to the start and stop commands.
31
+ :start_args: start <%= '<%= Rails.env %' + '>' %>
32
+ :stop_args: stop
33
+ # Time to wait after sending the stop command, before killing the daemon.
34
+ :delay_before_kill: 1.0
35
+ # If this is a consumer of another daemon (like starling), make sure the start
36
+ # order index is bigger than the other daemons' start order index.
37
+ :start_order: 1
38
+ # daemonz will ignore this daemon configuration when this flag is true
39
+ :disabled: false
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Load Rails.
4
+ ENV['RAILS_ENV'] = ARGV[1] if ARGV[1]
5
+ require File.dirname(__FILE__) + '/../../config/environment.rb'
6
+
7
+ # TODO: More ARGV-based setup here.
8
+
9
+
10
+ # Restore timestamps in the log.
11
+ class Logger
12
+ def format_message(severity, timestamp, progname, msg)
13
+ "#{severity[0,1]} [#{timestamp} PID:#{$$}] #{progname}: #{msg}\n"
14
+ end
15
+ end
16
+
17
+
18
+ require 'simple-daemon'
19
+ class <%= class_name %> < SimpleDaemon::Base
20
+ SimpleDaemon::WORKING_DIRECTORY = Rails.root.join 'log'
21
+
22
+ def self.start
23
+ STDOUT.sync = true
24
+ @logger = Logger.new(STDOUT)
25
+ @logger.level = Rails.env.production?
26
+ if Rails.env.development?
27
+ # Disable SQL logging in debugging.
28
+ # This is handy if your daemon queries the database often.
29
+ ActiveRecord::Base.logger.level = Logger::INFO
30
+ end
31
+
32
+ @logger.info "Starting daemon #{self.name}"
33
+
34
+ loop do
35
+ begin
36
+ # TODO: execute some tasks in the background repeatedly
37
+
38
+ # YOUR CODE HERE
39
+
40
+ # Optional. Sleep between tasks.
41
+ Kernel.sleep 1
42
+ rescue Exception => e
43
+ # This gets thrown when we need to get out.
44
+ raise if e.kind_of? SystemExit
45
+
46
+ @logger.error "Error in daemon #{self.name} - #{e.class.name}: #{e}"
47
+ @logger.info e.backtrace.join("\n")
48
+
49
+ # If something bad happened, it usually makes sense to wait for some
50
+ # time, so any external issues can settle.
51
+ Kernel.sleep 5
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.stop
57
+ @logger.info "Stopping daemon #{self.name}"
58
+ end
59
+ end
60
+
61
+ <%= class_name %>.daemonize
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class <%= class_name %>Test < ActionController::IntegrationTest
4
+ fixtures :all
5
+
6
+ # Normally, Rails runs the entire test in a transaction, so the database
7
+ # changes done in test are isolated from the database changes made by daemons.
8
+ # The line can be removed if the test and the daemon don't communicate via the
9
+ # database.
10
+ self.use_transactional_fixtures = false
11
+
12
+ test "daemon interactions" do
13
+ # stuff that should be done before the daemon runs (e.g. database setup)
14
+
15
+ Daemonz.with_daemons do
16
+ # test interactions with the daemon
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,8 @@
1
1
  module Daemonz
2
- @logger = RAILS_DEFAULT_LOGGER
3
- class <<self
4
- attr_reader :logger
2
+ @logger = Rails.logger
3
+
4
+ def self.logger
5
+ @logger || Rails.logger
5
6
  end
6
7
 
7
8
  def self.configure_logger
@@ -13,7 +14,9 @@ module Daemonz
13
14
  @logger = Logger.new(STDERR)
14
15
  @logger.level = Logger::DEBUG
15
16
  when 'rails'
16
- @logger = RAILS_DEFAULT_LOGGER
17
+ @logger = Rails.logger
18
+ else
19
+ @logger = Rails.logger
17
20
  end
18
21
  end
19
22
  end
@@ -13,7 +13,7 @@ module Daemonz
13
13
 
14
14
  # Complete startup used by rake:start and at Rails plug-in startup.
15
15
  def self.safe_start(options = {})
16
- daemonz_config = File.join(RAILS_ROOT, 'config', 'daemonz.yml')
16
+ daemonz_config = Rails.root.join 'config', 'daemonz.yml'
17
17
  Daemonz.configure daemonz_config, options
18
18
 
19
19
  if Daemonz.config[:is_master]
@@ -25,7 +25,7 @@ module Daemonz
25
25
  # Complete shutdown used by rake:start and at Rails application exit.
26
26
  def self.safe_stop(options = {})
27
27
  if options[:configure]
28
- daemonz_config = File.join(RAILS_ROOT, 'config', 'daemonz.yml')
28
+ daemonz_config = Rails.root.join 'config', 'daemonz.yml'
29
29
  Daemonz.configure daemonz_config, options
30
30
  end
31
31
  if Daemonz.config[:is_master]
@@ -0,0 +1,24 @@
1
+ require 'daemonz'
2
+ require 'rails'
3
+
4
+ # :nodoc: namespace
5
+ module Daemonz
6
+
7
+ # Railtie for the daemonz plugin.
8
+ class Railtie < Rails::Railtie
9
+ initializer :control_daemon_processes do
10
+ Daemonz.safe_start
11
+ at_exit { Daemonz.safe_stop unless Daemonz.keep_daemons_at_exit }
12
+ end
13
+
14
+ rake_tasks do
15
+ load 'daemonz/tasks/daemonz_tasks.rake'
16
+ end
17
+
18
+ generators do
19
+ require 'daemonz/generators/config/config_generator.rb'
20
+ require 'daemonz/generators/daemon/daemon_generator.rb'
21
+ end
22
+ end # class Daemonz::Railtie
23
+
24
+ end # namespace Daemonz
@@ -0,0 +1,14 @@
1
+ namespace :daemons do
2
+ desc "(testing only) Starts the daemons in config/daemonz.yml"
3
+ task :start => :environment do
4
+ Daemonz.safe_start :force_enabled => true, :override_logger => 'stdout'
5
+ Daemonz.keep_daemons_at_exit = true
6
+ end
7
+
8
+ desc "(testing only) Stops the daemons in config/daemonz.yml"
9
+ task :stop => :environment do
10
+ Daemonz.safe_stop :force_enabled => true, :configure => true,
11
+ :override_logger => 'stdout'
12
+ Daemonz.keep_daemons_at_exit = true
13
+ end
14
+ end
data/lib/daemonz.rb CHANGED
@@ -8,3 +8,5 @@ require 'daemonz/logging.rb'
8
8
  require 'daemonz/manage.rb'
9
9
  require 'daemonz/master.rb'
10
10
  require 'daemonz/process.rb'
11
+
12
+ require 'daemonz/railtie.rb' if defined?(Rails)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 0
9
- version: 0.3.0
8
+ - 1
9
+ version: 0.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Victor Costan
@@ -53,16 +53,27 @@ files:
53
53
  - MIT-LICENSE
54
54
  - README.textile
55
55
  - Rakefile
56
+ - VERSION
56
57
  - config_template.yml
57
58
  - daemonz.gemspec
58
59
  - init.rb
59
60
  - lib/daemonz.rb
60
61
  - lib/daemonz/config.rb
62
+ - lib/daemonz/generators/config/config_generator.rb
63
+ - lib/daemonz/generators/config/templates/config.yml
64
+ - lib/daemonz/generators/config/templates/prepackaged/ferret.yml
65
+ - lib/daemonz/generators/config/templates/prepackaged/starling.yml
66
+ - lib/daemonz/generators/daemon/daemon_generator.rb
67
+ - lib/daemonz/generators/daemon/templates/config.yml
68
+ - lib/daemonz/generators/daemon/templates/daemon.rb.erb
69
+ - lib/daemonz/generators/daemon/templates/integration_test.rb.erb
61
70
  - lib/daemonz/killer.rb
62
71
  - lib/daemonz/logging.rb
63
72
  - lib/daemonz/manage.rb
64
73
  - lib/daemonz/master.rb
65
74
  - lib/daemonz/process.rb
75
+ - lib/daemonz/railtie.rb
76
+ - lib/daemonz/tasks/daemonz_tasks.rake
66
77
  has_rdoc: true
67
78
  homepage: http://github.com/costan/daemonz
68
79
  licenses: []