module RailsDaemons::Worker

Public Instance Methods

daemonize() click to toggle source
# File lib/rails_daemons/worker.rb, line 10
def daemonize
  pid = fork do
    $logger = Utils.logger( "#{self.class.worker_name}.#{Rails.env}.log" )
    $logger.level = Logger::INFO

    working
  end

  Process.detach( pid )

  puts "#{self.class.worker_name} (#{pid}) started."
end
logger() click to toggle source
# File lib/rails_daemons/worker.rb, line 63
def logger
  $logger
end
redirect_io() click to toggle source
# File lib/rails_daemons/worker.rb, line 75
def redirect_io
  # https://github.com/ghazel/daemons/blob/d09e132ea67001ba4d6bf6481fb53c4bd4fd9195/lib/daemons/daemonize.rb#L241
  begin; STDIN.reopen "/dev/null"; rescue ::Exception; end

  begin
    STDOUT.reopen( Utils.join( 'log', "#{self.class.worker_name}.#{Rails.env}.out.log" ), "a" )
    STDOUT.sync = true
  rescue ::Exception
    begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
  end

  begin; STDERR.reopen STDOUT; rescue ::Exception; end
  STDERR.sync = true
end
reopen_logs() click to toggle source
# File lib/rails_daemons/worker.rb, line 51
def reopen_logs
  pid = self.class.get_pid

  logger.info "Reopen logs #{self.class.worker_name} (#{pid})"

  Unicorn::Util.reopen_logs

  logger.info "Logs reopened #{self.class.worker_name} (#{pid})"

  $reopening = false
end
shutdown() click to toggle source
# File lib/rails_daemons/worker.rb, line 124
def shutdown
end
shutdowning() click to toggle source
# File lib/rails_daemons/worker.rb, line 102
def shutdowning
  pid = self.class.get_pid

  logger.info "Graceful shutdown #{self.class.worker_name} (#{pid})"
  $stop_working = true

  shutdown

  puts "#{self.class.worker_name} (#{pid}) stopped."

  exit 0

rescue => e
  logger.error "exiting #{self.class.worker_name}, unable to stop gracefully"
  logger.error e.message
  logger.error e.backtrace.join( "\n" )

  File.remove( self.class.pid_file ) if File.exists?( self.class.pid_file )

  exit 1
end
start() click to toggle source
# File lib/rails_daemons/worker.rb, line 90
def start
  puts "Start #{self.class.name}"
end
starting() click to toggle source
# File lib/rails_daemons/worker.rb, line 67
def starting
  $0 = "RAILS_ENV=#{Rails.env} " + Utils.join( '' ).to_s + " bundle exec thor daemon:start #{self.class}"

  redirect_io
  start
  store_pid
end
stop_old_worker() click to toggle source
# File lib/rails_daemons/worker.rb, line 127
def stop_old_worker
  return unless File.file?( self.class.pid_file )

  pid = self.class.get_pid

  unless self.class.running?( pid )
    logger.info "Stale pid file (#{pid}), deleting"
    File.delete( self.class.pid_file )

    return
  end

  logger.info "Killing old worker (#{pid})"
  Process.kill( "INT", pid )

  # wait for die
  32.times do
    sleep 3

    unless self.class.running?( pid )
      logger.info "Old worker (#{pid}) died by himself"

      return
    end
  end

  return unless self.class.running?( pid )

  logger.error "Old worker (#{pid}) isn't going to die, doing kill -9"

  Process.kill( "KILL", pid )
  File.delete( self.class.pid_file )
end
store_pid() click to toggle source
# File lib/rails_daemons/worker.rb, line 161
def store_pid
  FileUtils.mkdir_p( File.dirname( self.class.pid_file ) )
  IO.write( self.class.pid_file, Process.pid.to_s )
end
tick() click to toggle source
# File lib/rails_daemons/worker.rb, line 98
def tick
  1.0
end
work() click to toggle source
# File lib/rails_daemons/worker.rb, line 94
def work
  raise 'Not implemented! Write your own work'
end
working() click to toggle source
# File lib/rails_daemons/worker.rb, line 23
def working
  $stop_working = false
  $reopening = false

  Signal.trap "INT" do
    Thread.new do
      shutdowning
    end
  end

  Signal.trap "USR1" do
    $reopening = true
  end

  stop_old_worker

  starting

  loop do
    reopen_logs if $reopening
    break if $stop_working

    work

    sleep tick
  end
end