Class: ProcessBot::Process::Runner

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command:, logger:, options:) ⇒ Runner

Returns a new instance of Runner.



6
7
8
9
10
11
12
# File 'lib/process_bot/process/runner.rb', line 6

def initialize(command:, logger:, options:)
  @command = command
  @logger = logger
  @monitor = Monitor.new
  @options = options
  @output = []
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def command
  @command
end

#exit_statusObject (readonly)

Returns the value of attribute exit_status.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def exit_status
  @exit_status
end

#loggerObject (readonly)

Returns the value of attribute logger.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def logger
  @logger
end

#monitorObject (readonly)

Returns the value of attribute monitor.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def monitor
  @monitor
end

#optionsObject (readonly)

Returns the value of attribute options.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def options
  @options
end

#pidObject (readonly)

Returns the value of attribute pid.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def pid
  @pid
end

#stop_timeObject (readonly)

Returns the value of attribute stop_time.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def stop_time
  @stop_time
end

#subprocess_pidObject (readonly)

Returns the value of attribute subprocess_pid.



4
5
6
# File 'lib/process_bot/process/runner.rb', line 4

def subprocess_pid
  @subprocess_pid
end

Instance Method Details

#find_sidekiq_pidObject

rubocop:disable Metrics/AbcSize



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/process_bot/process/runner.rb', line 72

def find_sidekiq_pid # rubocop:disable Metrics/AbcSize
  Thread.new do
    while running? && !pid
      Knj::Unix_proc.list("grep" => "sidekiq") do |process|
        cmd = process.data.fetch("cmd")

        if /sidekiq ([0-9]+\.[0-9]+\.[0-9]+) (#{options.possible_process_titles_joined_regex})/.match?(cmd)
          sidekiq_pid = process.data.fetch("pid").to_i

          begin
            sidekiq_pgid = Process.getpgid(sidekiq_pid)
          rescue Errno::ESRCH
            # Process no longer running
          end

          if subprocess_pgid == sidekiq_pgid
            puts "FOUND PID: #{sidekiq_pid}"

            @pid = sidekiq_pid
            options.events.call(:on_process_started, pid: pid)

            break
          else
            puts "PGID didn't match - Sidekiq: #{sidekiq_pgid} Own: #{subprocess_pgid}"
          end
        end
      end

      unless pid
        puts "Waiting 1 second before trying to find Sidekiq PID again"
        sleep 1
      end
    end
  end
end

#output(output:, type:) ⇒ Object



14
15
16
# File 'lib/process_bot/process/runner.rb', line 14

def output(output:, type:)
  logger.log(output, type: type)
end

#runObject

rubocop:disable Metrics/AbcSize



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
# File 'lib/process_bot/process/runner.rb', line 22

def run # rubocop:disable Metrics/AbcSize
  @start_time = Time.new
  stderr_reader, stderr_writer = IO.pipe

  require "pty"

  PTY.spawn(command, err: stderr_writer.fileno) do |stdout, _stdin, pid|
    @subprocess_pid = pid
    logger.logs "Command running with PID #{pid}: #{command}"

    stdout_reader_thread = Thread.new do
      stdout.each_char do |chunk|
        monitor.synchronize do
          output(type: :stdout, output: chunk)
        end
      end
    rescue Errno::EIO
      # Process done
    ensure
      status = Process::Status.wait(subprocess_pid, 0)

      @exit_status = status.exitstatus
      stderr_writer.close
    end

    stderr_reader_thread = Thread.new do
      stderr_reader.each_char do |chunk|
        monitor.synchronize do
          output(type: :stderr, output: chunk)
        end
      end
    end

    find_sidekiq_pid

    stdout_reader_thread.join
    stderr_reader_thread.join

    @stop_time = Time.new
  end
end

#running?Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/process_bot/process/runner.rb', line 18

def running?
  !stop_time
end

#sidekiq_app_nameObject



68
69
70
# File 'lib/process_bot/process/runner.rb', line 68

def sidekiq_app_name
  options.fetch(:application)
end

#subprocess_pgidObject



64
65
66
# File 'lib/process_bot/process/runner.rb', line 64

def subprocess_pgid
  @subprocess_pgid ||= Process.getpgid(subprocess_pid)
end