Class: MailyHerald::CLI

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/maily_herald/cli.rb

Instance Method Summary collapse

Instance Method Details

#daemon_running?Boolean


253
254
255
256
257
# File 'lib/maily_herald/cli.rb', line 253

def daemon_running?
  read_pid > 0 && Process.kill(0, read_pid)
rescue
  return false
end

#daemonizeObject

Raises:

  • (ArgumentError)

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/maily_herald/cli.rb', line 197

def daemonize
  return unless options[:daemon]

  raise ArgumentError, "You really should set a logfile if you're going to daemonize" unless options[:logfile]
  files_to_reopen = []
  ObjectSpace.each_object(File) do |file|
    files_to_reopen << file unless file.closed?
  end

  Process.daemon(true, true)

  files_to_reopen.each do |file|
    begin
      file.reopen file.path, "a+"
      file.sync = true
    rescue ::Exception
    end
  end

  [$stdout, $stderr].each do |io|
    File.open(options[:logfile], 'ab') do |f|
      io.reopen(f)
    end
    io.sync = true
  end
  $stdin.reopen('/dev/null')

  initialize_logger
end

#initialize_loggerObject


102
103
104
105
106
107
108
109
110
111
# File 'lib/maily_herald/cli.rb', line 102

def initialize_logger
  opts = {
    level: options[:verbose] ? Logger::DEBUG : Logger::INFO,
    progname: "cli",
  }
  opts[:target] = options[:logfile] if options[:logfile]

  MailyHerald::Logging.initialize(opts)
  MailyHerald.logger.info "Started with options: #{options}"
end

#kill_daemonObject


259
260
261
262
263
264
# File 'lib/maily_herald/cli.rb', line 259

def kill_daemon
  Process.kill("INT", read_pid) if read_pid > 0
  return true
rescue
  return false
end

#optionsObject


193
194
195
# File 'lib/maily_herald/cli.rb', line 193

def options
  MailyHerald.options
end

#paperboyObject


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
# File 'lib/maily_herald/cli.rb', line 19

def paperboy
  if options[:action] == :stop
    kill_daemon || exit(0)
  elsif options[:action] == :ping
    if daemon_running?
      puts "PONG"
      exit(0)
    else
      puts "No response..."
      exit(1)
    end
  else
    if options[:action] == :restart 
      kill_daemon 
      5.times do
        if daemon_running?
          sleep 2
        else
          break
        end

        exit(0) if daemon_running?
      end
    end
    exit(0) if options[:action] == :start && daemon_running?

    daemonize
    write_pid

    self_read, self_write = IO.pipe

    %w(INT TERM USR1 USR2).each do |sig|
      trap sig do
        self_write.puts(sig)
      end
    end

    # We don't want to load whole app and its initializers just to set up Sidekiq client
    # so let's just do that instead:
    Sidekiq.redis = {url: options[:redis_url], namespace: options[:redis_namespace]}

    redis = MailyHerald.redis
    MailyHerald.logger.info "MailyHerald running in #{RUBY_DESCRIPTION}"

    if !options[:daemon]
      MailyHerald.logger.info 'Starting processing, hit Ctrl-C to stop'
    end

    begin
      worker = Thread.new do
        while true
          unless MailyHerald::Manager.job_enqueued?
            MailyHerald.run_all 
          else
            # TODO: this is not logged
            #MailyHerald.logger.error 'Unable to queue job'
          end

          sleep 20
        end
      end

      while readable_io = IO.select([self_read])
        signal = readable_io.first[0].gets.strip
        handle_signal(signal)
      end
    rescue Interrupt
      MailyHerald.logger.info 'Shutting down'
      worker.exit
      reset_pid
      exit(0)
    end
  end
end

#parse(args = ARGV) ⇒ Object


14
15
16
17
# File 'lib/maily_herald/cli.rb', line 14

def parse(args=ARGV)
  setup_options(args)
  initialize_logger
end

#parse_config(cfile) ⇒ Object


184
185
186
187
188
189
190
191
# File 'lib/maily_herald/cli.rb', line 184

def parse_config(cfile)
  opts = {}
  if File.exist?(cfile)
    opts = YAML.load(ERB.new(IO.read(cfile)).result)
    opts = opts.merge(opts.delete(@environment) || {})
  end
  opts
end

#parse_options(argv) ⇒ Object


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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/maily_herald/cli.rb', line 113

def parse_options(argv)
  opts = {}
  @parsers = {}

  @parsers[:paperboy] = OptionParser.new do |o|
    o.banner = "maily_herald paperboy [options]"

    o.on "--start", "Start Paperboy daemon" do |arg|
      opts[:action] = :start
      opts[:daemon] = true
    end

    o.on "--stop", "Stop Paperboy daemon" do |arg|
      opts[:action] = :stop
      opts[:daemon] = true
    end

    o.on "--restart", "Restart Paperboy daemon" do |arg|
      opts[:action] = :restart
      opts[:daemon] = true
    end

    o.on "--ping", "Check if Paperboy daemon is running" do |arg|
      opts[:action] = :ping
      opts[:daemon] = true
    end

    o.on '-L', '--logfile PATH', "path to writable logfile" do |arg|
      opts[:logfile] = arg
    end

    o.on '-P', '--pidfile PATH', "path to pidfile" do |arg|
      opts[:pidfile] = arg
    end
  end

  @parsers[:generic] = OptionParser.new do |o|
    o.banner = "maily_herald [paperboy] [options]"

    o.separator ""
    o.separator "Common options:"

    o.on '-c', '--config PATH', "path to YAML config file" do |arg|
      opts[:config_file] = arg
    end

    o.on '-e', '--environment ENV', "Application environment" do |arg|
      opts[:environment] = arg
    end

    o.on "-v", "--verbose", "Print more verbose output" do |arg|
      opts[:verbose] = arg
    end

    o.on_tail "-h", "--help", "Show help" do
      puts @parsers[:generic]
      puts
      puts @paperboy_parser
      exit 1
    end
  end

  if %w{paperboy}.include?(argv.first)
    opts[:mode] = argv.first.to_sym
    @parsers[argv.first.to_sym].parse!(argv)
  end
  @parsers[:generic].parse!(argv)

  opts
end

#read_pidObject


237
238
239
240
241
# File 'lib/maily_herald/cli.rb', line 237

def read_pid
  if path = options[:pidfile]
    File.read(path).to_i
  end
end

#reset_pidObject


243
244
245
246
247
248
249
250
251
# File 'lib/maily_herald/cli.rb', line 243

def reset_pid
  return unless options[:daemon]

  if path = options[:pidfile]
    File.open(path, 'w') do |f|
      f.puts nil
    end
  end
end

#setup_options(args) ⇒ Object


94
95
96
97
98
99
100
# File 'lib/maily_herald/cli.rb', line 94

def setup_options(args)
  cli = parse_options(args)

  set_environment cli[:environment]

  MailyHerald.options = MailyHerald.read_options(cli[:config_file] || "config/maily_herald.yml").merge(cli)
end

#write_pidObject


227
228
229
230
231
232
233
234
235
# File 'lib/maily_herald/cli.rb', line 227

def write_pid
  return unless options[:daemon]

  if path = options[:pidfile]
    File.open(path, 'w') do |f|
      f.puts Process.pid
    end
  end
end