module Daemonic class Worker include Logging attr_reader :index, :config def initialize(options) @index = options.fetch(:index) @config = options.fetch(:config) end def start @pid = Process.spawn( {"DAEMON_WORKER_NUMBER" => index.to_s}, *Array(config.command), {:chdir => config.working_dir} ) sleep 0.1 info "#{to_s} Starting." pidfile.write wait_for { running? } info "#{to_s} Started!" end def stop Process.kill("TERM", pid) info "#{to_s} Stopping." Process.waitpid(pid) rescue Errno::ECHILD, Errno::ESRCH warn "#{to_s} Already stopped." ensure pidfile.clean @pid = nil end def restart info "#{to_s} Restarting." stop start end def hup Process.kill("HUP", pid) end def monitor if not running? warn "#{to_s} Not running." start end end def running? if @pid !Process.waitpid(pid, Process::WNOHANG) rescue false else false end end private def pid @pid || raise("unknown pid") end def pidfile Pidfile.new( pid: pid, config: config, index: index, ) end def wait_for(timeout=2) deadline = Time.now + timeout until Time.now >= deadline result = yield if result return else sleep 0.1 end end warn "#{to_s} It took too long to start." end def to_s "" end end end