class Opener::Daemons::Controller

CLI controller for a component.

@!attribute [r] name

The name of the daemon.
@return [String]

@!attribute [r] exec_path

The path to the script to daemonize.
@return [String]

@!attribute [r] parser

@return [Opener::Daemons::OptionParser]

Attributes

exec_path[R]
name[R]
parser[R]

Public Class Methods

new(options = {}) click to toggle source

@param [Hash] options

@option options [String] :name @option options [String] :exec_path

# File lib/opener/daemons/controller.rb, line 26
def initialize(options = {})
  @name      = options.fetch(:name)
  @exec_path = options.fetch(:exec_path)
  @parser    = configure_slop
end

Public Instance Methods

configure_slop() click to toggle source

@return [Slop]

# File lib/opener/daemons/controller.rb, line 44
def configure_slop
  parser = OptionParser.new(name)

  parser.parser.run do |opts, args|
    command  = args.shift
    new_args = args.reject { |arg| arg == '--' }

    case command
    when 'start'
      start_background(opts, new_args)
    when 'stop'
      stop(opts)
    when 'restart'
      stop(opts)
      start_background(opts, new_args)
    else
      start_foreground(opts, new_args)
    end
  end

  return parser
end
run(argv = ARGV) click to toggle source

Runs the CLI

@param [Array] argv CLI arguments to parse.

# File lib/opener/daemons/controller.rb, line 37
def run(argv = ARGV)
  parser.parse(argv)
end
setup_env(options) click to toggle source

Returns a Hash containing the various environment variables to set for the daemon (on top of the current environment variables).

@param [Slop] options @return [Hash]

# File lib/opener/daemons/controller.rb, line 135
def setup_env(options)
  newrelic_config = File.expand_path(
    '../../../../config/newrelic.yml',
    __FILE__
  )

  env = ENV.to_hash.merge(
    'INPUT_QUEUE'    => options[:input].to_s,
    'DAEMON_THREADS' => options[:threads].to_s,
    'OUTPUT_BUCKET'  => options[:bucket].to_s,
    'NRCONFIG'       => newrelic_config,
    'APP_ROOT'       => File.expand_path('../../../../', __FILE__),
    'APP_NAME'       => name
  )

  if !env['RAILS_ENV'] and env['RACK_ENV']
    env['RAILS_ENV'] = env['RACK_ENV']
  end

  unless options[:'disable-syslog']
    env['ENABLE_SYSLOG'] = 'true'
  end

  return env
end
start_background(options, argv = []) click to toggle source

Starts the daemon in the background.

@param [Slop] options @param [Array] argv

# File lib/opener/daemons/controller.rb, line 83
def start_background(options, argv = [])
  pidfile = Pidfile.new(options[:pidfile])
  pid     = Process.spawn(
    setup_env(options),
    exec_path,
    *argv,
    out: '/dev/null',
    err: '/dev/null',
    in:  '/dev/null'
  )

  pidfile.write(pid)

  begin
    # Wait until the process has _actually_ started.
    Timeout.timeout(options[:wait]) { sleep(0.5) until pidfile.alive? }

    puts "Process with Pidfile #{pidfile.read} started"
  rescue Timeout::Error
    pidfile.unlink

    abort "Failed to start the process after #{options[:wait]} seconds"
  end
end
start_foreground(options, argv = []) click to toggle source

Runs the daemon in the foreground.

@param [Slop] options @param [Array] argv

# File lib/opener/daemons/controller.rb, line 73
def start_foreground(options, argv = [])
  exec(setup_env(options), exec_path, *argv)
end
stop(options) click to toggle source

Stops the daemon.

@param [Slop] options

# File lib/opener/daemons/controller.rb, line 113
def stop(options)
  pidfile = Pidfile.new(options[:pidfile])

  if pidfile.alive?
    id = pidfile.read

    pidfile.terminate
    pidfile.unlink

    puts "Process with Pidfile #{id.inspect} terminated"
  else
    abort 'Process already terminated or you are not allowed to terminate it'
  end
end