daemonz 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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: []