veloper/zeusd

View on GitHub
lib/zeusd/daemon.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Zeusd
  class Daemon
    attr_reader :cwd, :verbose, :child_process, :status

    def initialize(options = {})
      @cwd     = Pathname.new(options[:cwd] || Dir.pwd).realpath
      @verbose = !!options[:verbose]
    end

    def start!(options = {})
      start_child_process!

      @process = Zeusd::Process.find(child_process.pid)

      if options.fetch(:block, false)
        sleep(3) until status.finished?
      end

      self
    end

    def restart!(options = {})
      stop!.start!(options)
    end

    def stop!
      return self unless process

      # Kill process tree and wait for exits
      process.kill!(:recursive => true, :signal => "KILL", :wait => true)

      # Clean up socket file if stil exists
      (zeus_socket.delete rescue nil) if zeus_socket.exist?

      @process = nil

      self
    end

    def status_queue
      queue  = Queue.new
      status = Log::Status.new(File.new(zeus_log.to_path, 'r'))

      queue << status.to_cli
      status.on_update {|x| queue << x.to_cli }
      status.record!

      queue
    end

    def process
      @process ||= Process.all.find {|p| !!p.command[/zeus.*start$/] && p.cwd == cwd }
    end

    def finished?
      status.finished?
    end

    def zeus_socket
      cwd.join('.zeus.sock')
    end

    def zeus_log
      cwd.join('log', 'zeus.log').tap do |path|
        FileUtils.touch(path.to_path)
      end
    end

    def verbose?
      !!verbose
    end

    def to_json(*args)
      {
        :class   => self.class.name,
        :cwd     => cwd.to_path,
        :verbose => verbose,
        :process => process
      }.to_json(*args)
    end

    protected

    def start_child_process!
       # Truncate and cast to File instance
      zeus_log.open("w") {}
      std_file = File.new(zeus_log.to_path, 'w+')
      std_file.sync = true

      # Prep and Start child process
      @child_process = ChildProcess.build("zeus", "start")
      @child_process.environment["BUNDLE_GEMFILE"] = cwd.join("Gemfile").to_path
      @child_process.io.stderr = std_file
      @child_process.io.stdout = std_file
      @child_process.cwd       = cwd.to_path
      @child_process.detach    = true
      @child_process.start

      @status = Log::Status.new(std_file)
      @status.on_update do |status, line|
        puts status.to_cli if verbose?
      end
      @status.record!

      sleep 0.1 until @status.started?

      @child_process
    end

    include Zeusd::DaemonTracker
  end
end