Class: Ak47::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/ak47/runner.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = nil, &blk) ⇒ Runner

Returns a new instance of Runner.



5
6
7
8
9
10
11
12
13
# File 'lib/ak47/runner.rb', line 5

def initialize(opts = nil, &blk)
  @watch_dirs = Array(opts && opts[:watch_dirs] || Dir.pwd)
  @maximum    = opts && opts[:maximum]
  @interval   = opts && opts[:interval] || 0.01
  @error_time = opts && opts[:error_time] || 5
  @command    = opts && opts[:command]
  @interrupt  = opts && opts.key?(:interrupt) ? opts[:interrupt] : true
  @blk        = blk
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def command
  @command
end

#error_timeObject (readonly)

Returns the value of attribute error_time.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def error_time
  @error_time
end

#interruptObject (readonly)

Returns the value of attribute interrupt.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def interrupt
  @interrupt
end

#intervalObject (readonly)

Returns the value of attribute interval.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def interval
  @interval
end

#maximumObject (readonly)

Returns the value of attribute maximum.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def maximum
  @maximum
end

#watch_dirsObject (readonly)

Returns the value of attribute watch_dirs.



3
4
5
# File 'lib/ak47/runner.rb', line 3

def watch_dirs
  @watch_dirs
end

Instance Method Details

#kill_pidObject



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ak47/runner.rb', line 76

def kill_pid
  if @pid
    begin
      unless wait_pid('INT')
        unless wait_pid('KILL')
          raise "[Unable to kill #{@pid}]"
        end
      end
    rescue Errno::ESRCH
    end
  end
end

#startObject



15
16
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
# File 'lib/ak47/runner.rb', line 15

def start
  listeners = watch_dirs.map {|wd| Guard::Listener.select_and_init(:watchdir => wd, :watch_all_modifications => true) }
  change_detected = false
  running = false
  listeners.each do |l|
    l.on_change { |f|
      if @interrupt
        Thread.main.raise Reload, "File system changed"
      else
        change_detected = true
        Thread.main.raise Reload, "File system changed" unless running
      end
    }
    Thread.new { l.start }
  end

  at_exit { kill_pid }

  puts "[Starting ak47 #{VERSION} in #{watch_dirs.join(', ')}]".green
  loop do
    begin
      puts "[Running... #{Time.new.to_s}]".yellow
      puts "# #{command}" if command
      if maximum 
        @thread = Thread.new { sleep maximum; Thread.main.raise Reload, "Cancelled due to maximum time" }
      end
      running = true
      change_detected = false
      begin
        @pid = fork(&@blk)
        Process.detach(@pid)
        _, status = Process.waitpid2(@pid)
      rescue Errno::ECHILD
        @pid = nil
      ensure
        running = false
      end
      @thread.kill if @thread
      if @pid.nil? || status.success?
        if change_detected
          puts "[Change detected while previously running]".green
          change_detected = false
        else
          puts "[Terminated, waiting for file system change]".green
          maximum ? sleep(interval) : sleep
        end
      else
        puts "[Terminated abnormally (#{status.inspect}), retrying in 5s]".red
        sleep error_time
      end
    rescue Reload => e
      kill_pid
      sleep interval
      puts "[Reloading (#{e.message}) #{Time.new.to_s}]".yellow
    rescue Interrupt
      puts "[Interrupted, exiting]".yellow
      exit
    end
  end
end

#wait_pid(sig) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ak47/runner.rb', line 89

def wait_pid(sig)
  count = 0
  while count < 5
    begin
      Process.kill(sig, @pid)
      count += 1
      sleep 1
    rescue Errno::ESRCH
      @pid = nil
      return true
    end
  end
  false
end