Class: Opener::Daemons::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/opener/daemons/controller.rb

Overview

CLI controller for a component.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Controller

Returns a new instance of Controller.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :name (String)
  • :exec_path (String)


26
27
28
29
30
# 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

Instance Attribute Details

#exec_pathString (readonly)

The path to the script to daemonize.

Returns:

  • (String)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/opener/daemons/controller.rb', line 17

class Controller
  attr_reader :name, :exec_path, :parser

  ##
  # @param [Hash] options
  #
  # @option options [String] :name
  # @option options [String] :exec_path
  #
  def initialize(options = {})
    @name      = options.fetch(:name)
    @exec_path = options.fetch(:exec_path)
    @parser    = configure_slop
  end

  ##
  # Runs the CLI
  #
  # @param [Array] argv CLI arguments to parse.
  #
  def run(argv = ARGV)
    parser.parse(argv)
  end

  ##
  # @return [Slop]
  #
  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

  ##
  # Runs the daemon in the foreground.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  def start_foreground(options, argv = [])
    exec(setup_env(options), exec_path, *argv)
  end

  ##
  # Starts the daemon in the background.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  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

  ##
  # Stops the daemon.
  #
  # @param [Slop] options
  #
  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

  ##
  # 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]
  #
  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
end

#nameString (readonly)

The name of the daemon.

Returns:

  • (String)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/opener/daemons/controller.rb', line 17

class Controller
  attr_reader :name, :exec_path, :parser

  ##
  # @param [Hash] options
  #
  # @option options [String] :name
  # @option options [String] :exec_path
  #
  def initialize(options = {})
    @name      = options.fetch(:name)
    @exec_path = options.fetch(:exec_path)
    @parser    = configure_slop
  end

  ##
  # Runs the CLI
  #
  # @param [Array] argv CLI arguments to parse.
  #
  def run(argv = ARGV)
    parser.parse(argv)
  end

  ##
  # @return [Slop]
  #
  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

  ##
  # Runs the daemon in the foreground.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  def start_foreground(options, argv = [])
    exec(setup_env(options), exec_path, *argv)
  end

  ##
  # Starts the daemon in the background.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  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

  ##
  # Stops the daemon.
  #
  # @param [Slop] options
  #
  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

  ##
  # 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]
  #
  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
end

#parserOpener::Daemons::OptionParser (readonly)



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/opener/daemons/controller.rb', line 17

class Controller
  attr_reader :name, :exec_path, :parser

  ##
  # @param [Hash] options
  #
  # @option options [String] :name
  # @option options [String] :exec_path
  #
  def initialize(options = {})
    @name      = options.fetch(:name)
    @exec_path = options.fetch(:exec_path)
    @parser    = configure_slop
  end

  ##
  # Runs the CLI
  #
  # @param [Array] argv CLI arguments to parse.
  #
  def run(argv = ARGV)
    parser.parse(argv)
  end

  ##
  # @return [Slop]
  #
  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

  ##
  # Runs the daemon in the foreground.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  def start_foreground(options, argv = [])
    exec(setup_env(options), exec_path, *argv)
  end

  ##
  # Starts the daemon in the background.
  #
  # @param [Slop] options
  # @param [Array] argv
  #
  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

  ##
  # Stops the daemon.
  #
  # @param [Slop] options
  #
  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

  ##
  # 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]
  #
  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
end

Instance Method Details

#configure_slopSlop

Returns:

  • (Slop)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 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) ⇒ Object

Runs the CLI

Parameters:

  • argv (Array) (defaults to: ARGV)

    CLI arguments to parse.



37
38
39
# File 'lib/opener/daemons/controller.rb', line 37

def run(argv = ARGV)
  parser.parse(argv)
end

#setup_env(options) ⇒ Hash

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

Parameters:

  • options (Slop)

Returns:

  • (Hash)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# 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 = []) ⇒ Object

Starts the daemon in the background.

Parameters:

  • options (Slop)
  • argv (Array) (defaults to: [])


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 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 = []) ⇒ Object

Runs the daemon in the foreground.

Parameters:

  • options (Slop)
  • argv (Array) (defaults to: [])


73
74
75
# File 'lib/opener/daemons/controller.rb', line 73

def start_foreground(options, argv = [])
  exec(setup_env(options), exec_path, *argv)
end

#stop(options) ⇒ Object

Stops the daemon.

Parameters:

  • options (Slop)


113
114
115
116
117
118
119
120
121
122
123
124
125
126
# 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