Skip to content

Commit

Permalink
daemon-kit skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
unknown authored and unknown committed Jul 6, 2010
0 parents commit 6b6a343
Show file tree
Hide file tree
Showing 22 changed files with 340 additions and 0 deletions.
48 changes: 48 additions & 0 deletions README
@@ -0,0 +1,48 @@
DaemonKit README
================

DaemonKit has generated a skeleton Ruby daemon for you to build on. Please read
through this file to ensure you get going quickly.

Directories
===========

bin/
bunnicula - Stub executable to control your daemon with

config/
Environment configuration files

lib/
Place for your libraries

libexec/
bunnicula.rb - Your daemon code

log/
Log files based on the environment name

spec/
rspec's home

tasks/
Place for rake tasks

vendor/
Place for unpacked gems and DaemonKit

tmp/
Scratch folder


Logging
=======

One of the biggest issues with writing daemons are gettign insight into what your
daemons are doing. Logging with DaemonKit is simplified as DaemonKit creates log
files per environment in log.

On all environments except production the log level is set to DEBUG, but you can
toggle the log level by sending the running daemon SIGUSR1 and SIGUSR2 signals.
SIGUSR1 will toggle between DEBUG and INFO levels, SIGUSR2 will blatantly set the
level to DEBUG.
6 changes: 6 additions & 0 deletions Rakefile
@@ -0,0 +1,6 @@
require File.dirname(__FILE__) + '/config/boot'

require 'rake'
require 'daemon_kit/tasks'

Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |rake| load rake }
7 changes: 7 additions & 0 deletions bin/bunnicula
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby
#
# Stub executable for bunnicula

require File.dirname(__FILE__) + '/../config/environment'

DaemonKit::Application.exec( DAEMON_ROOT + '/libexec/bunnicula-daemon.rb' )
28 changes: 28 additions & 0 deletions config/amqp.yml
@@ -0,0 +1,28 @@
# AMQP client configuration file

# These values will be used to configure the ampq gem, any values
# omitted will let the gem use it's own defaults.

# The configuration specifies the following keys:
# * user - Username for the broker
# * pass - Password for the broker
# * host - Hostname where the broker is running
# * vhost - Vhost to connect to
# * port - Port where the broker is running
# * ssl - Use ssl or not
# * timeout - Timeout

defaults: &defaults
user: guest
pass: guest
host: localhost
vhost: /

development:
<<: *defaults

test:
<<: *defaults

production:
<<: *defaults
12 changes: 12 additions & 0 deletions config/arguments.rb
@@ -0,0 +1,12 @@
# Argument handling for your daemon is configured here.
#
# You have access to two variables when this file is
# parsed. The first is +opts+, which is the object yielded from
# +OptionParser.new+, the second is +@options+ which is a standard
# Ruby hash that is later accessible through
# DaemonKit.arguments.options and can be used in your daemon process.

# Here is an example:
# opts.on('-f', '--foo FOO', 'Set foo') do |foo|
# @options[:foo] = foo
# end
59 changes: 59 additions & 0 deletions config/boot.rb
@@ -0,0 +1,59 @@
# Don't change this file!
# Configure your daemon in config/environment.rb

DAEMON_ROOT = "#{File.expand_path(File.dirname(__FILE__))}/.." unless defined?( DAEMON_ROOT )

module DaemonKit
class << self
def boot!
unless booted?
pick_boot.run
end
end

def booted?
defined? DaemonKit::Initializer
end

def pick_boot
(vendor_kit? ? VendorBoot : GemBoot).new
end

def vendor_kit?
File.exists?( "#{DAEMON_ROOT}/vendor/daemon_kit" )
end
end

class Boot
def run
load_initializer
DaemonKit::Initializer.run
end
end

class VendorBoot < Boot
def load_initializer
require "#{DAEMON_ROOT}/vendor/daemon_kit/lib/daemon_kit/initializer"
end
end

class GemBoot < Boot
def load_initializer
begin
gem 'daemon-kit'
require 'daemon_kit/initializer'
rescue Gem::LoadError => e
msg = <<EOF
You are missing the daemon-kit gem. Please install the following gems:
* Stable - sudo gem install daemon-kit
EOF
$stderr.puts msg
exit 1
end
end
end
end

DaemonKit.boot!
23 changes: 23 additions & 0 deletions config/environment.rb
@@ -0,0 +1,23 @@
# Be sure to restart your daemon when you modify this file

# Uncomment below to force your daemon into production mode
#ENV['DAEMON_ENV'] ||= 'production'

# Boot up
require File.join(File.dirname(__FILE__), 'boot')

DaemonKit::Initializer.run do |config|

# The name of the daemon as reported by process monitoring tools
config.daemon_name = 'bunnicula'

# Force the daemon to be killed after X seconds from asking it to
# config.force_kill_wait = 30

# Log backraces when a thread/daemon dies (Recommended)
# config.backtraces = true

# Configure the safety net (see DaemonKit::Safety)
# config.safety_net.handler = :mail # (or :hoptoad )
# config.safety_net.mail.host = 'localhost'
end
2 changes: 2 additions & 0 deletions config/environments/development.rb
@@ -0,0 +1,2 @@
# This is the same context as the environment.rb file, it is only
# loaded afterwards and only in the development environment
5 changes: 5 additions & 0 deletions config/environments/production.rb
@@ -0,0 +1,5 @@
# This is the same context as the environment.rb file, it is only
# loaded afterwards and only in the production environment

# Change the production log level to debug
#config.log_level = :debug
2 changes: 2 additions & 0 deletions config/environments/test.rb
@@ -0,0 +1,2 @@
# This is the same context as the environment.rb file, it is only
# loaded afterwards and only in the test environment
7 changes: 7 additions & 0 deletions config/initializers/bunnicula.rb
@@ -0,0 +1,7 @@
begin
require 'amqp'
require 'mq'
rescue LoadError
$stderr.puts "Missing amqp gem. Please run 'gem install amqp'."
exit 1
end
5 changes: 5 additions & 0 deletions config/post-daemonize/readme
@@ -0,0 +1,5 @@
# You can place files in here to be loaded after the code is daemonized.
#
# All the files placed here will just be required into the running
# process. This is the correct place to open any IO objects, establish
# database connections, etc.
12 changes: 12 additions & 0 deletions config/pre-daemonize/readme
@@ -0,0 +1,12 @@
# You can place files in here to be loaded before the code is daemonized.
#
# DaemonKit looks for a file named '<config.daemon_name>.rb' and loads
# that file first, and inside a DaemonKit::Initializer block. The
# remaning files then simply required into the running process.
#
# These files are mostly useful for operations that should fail blatantly
# before daemonizing, like loading gems.
#
# Be careful not to open any form of IO in here and expecting it to be
# open inside the running daemon since all IO instances are closed when
# daemonizing (including STDIN, STDOUT & STDERR).
2 changes: 2 additions & 0 deletions lib/bunnicula.rb
@@ -0,0 +1,2 @@
# Your starting point for daemon specific classes. This directory is
# already included in your load path, so no need to specify it.
37 changes: 37 additions & 0 deletions libexec/bunnicula-daemon.rb
@@ -0,0 +1,37 @@
# Generated amqp daemon

# Do your post daemonization configuration here
# At minimum you need just the first line (without the block), or a lot
# of strange things might start happening...
DaemonKit::Application.running! do |config|
# Trap signals with blocks or procs
# config.trap( 'INT' ) do
# # do something clever
# end
# config.trap( 'TERM', Proc.new { puts 'Going down' } )
end

# IMPORTANT CONFIGURATION NOTE
#
# Please review and update 'config/amqp.yml' accordingly or this
# daemon won't work as advertised.

# Run an event-loop for processing
DaemonKit::AMQP.run do
# Inside this block we're running inside the reactor setup by the
# amqp gem. Any code in the examples (from the gem) would work just
# fine here.

# Uncomment this for connection keep-alive
# AMQP.conn.connection_status do |status|
# DaemonKit.logger.debug("AMQP connection status changed: #{status}")
# if status == :disconnected
# AMQP.conn.reconnect(true)
# end
# end

amq = ::MQ.new
amq.queue('test').subscribe do |msg|
DaemonKit.logger.debug "Received message: #{msg.inspect}"
end
end
3 changes: 3 additions & 0 deletions script/console
@@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'daemon_kit/commands/console'
14 changes: 14 additions & 0 deletions script/destroy
@@ -0,0 +1,14 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))

begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/destroy'

ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:daemon, :test_unit]
RubiGen::Scripts::Destroy.new.run(ARGV)
14 changes: 14 additions & 0 deletions script/generate
@@ -0,0 +1,14 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))

begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/generate'

ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:daemon]
RubiGen::Scripts::Generate.new.run(ARGV)
11 changes: 11 additions & 0 deletions spec/bunnicula_spec.rb
@@ -0,0 +1,11 @@
require File.dirname(__FILE__) + '/spec_helper.rb'

# Time to add your specs!
# http://rspec.info/
describe "Place your specs here" do

it "find this spec in spec directory" do
violated "Be sure to write your specs"
end

end
1 change: 1 addition & 0 deletions spec/spec.opts
@@ -0,0 +1 @@
--colour
23 changes: 23 additions & 0 deletions spec/spec_helper.rb
@@ -0,0 +1,23 @@
DAEMON_ENV = 'test' unless defined?( DAEMON_ENV )

begin
require 'spec'
rescue LoadError
require 'rubygems'
gem 'rspec'
require 'spec'
end

require File.dirname(__FILE__) + '/../config/environment'
DaemonKit::Application.running!

Spec::Runner.configure do |config|
# == Mock Framework
#
# RSpec uses it's own mocking framework by default. If you prefer to
# use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
end
19 changes: 19 additions & 0 deletions tasks/rspec.rake
@@ -0,0 +1,19 @@
begin
require 'spec'
require 'spec/rake/spectask'
rescue LoadError
puts <<-EOS
To use rspec for testing you must install rspec gem:
gem install rspec
EOS
end

begin
desc "Run the specs under spec/"
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--options', "spec/spec.opts"]
t.spec_files = FileList['spec/**/*_spec.rb']
end
rescue NameError
# No loss, warning printed already
end

0 comments on commit 6b6a343

Please sign in to comment.