Class: Everywhere::Relay

Inherits:
Object
  • Object
show all
Defined in:
lib/everywhere/relay.rb

Overview

Reads one child's output off a pty and republishes it, one whole line at a time, tagged with its source.

every dev used to hand the dev server and desktop shell its own stdout and let them write straight to the terminal. That made two things impossible: telling which of four concurrent things printed a line, and keeping anything pinned to the bottom of the screen. Relaying costs a thread per child and buys both.

The full raw stream is also tee'd to a log file, matching what the builders already do with dist/ios-build.log — so nothing a filter hides is lost.

Constant Summary collapse

CHUNK =
4096
POLL =
0.1

Instance Method Summary collapse

Constructor Details

#initialize(io, source:, log: nil, filter: nil, on_line: nil) ⇒ Relay

on_line: an optional callback given every settled line before filtering. every dev uses it to notice the moment cargo actually starts the desktop shell — there is no other signal that the build turned into a running app.



26
27
28
29
30
31
32
# File 'lib/everywhere/relay.rb', line 26

def initialize(io, source:, log: nil, filter: nil, on_line: nil)
  @io = io
  @source = source
  @filter = filter
  @on_line = on_line
  @log = log && File.open(log, "w")
end

Instance Method Details

#runObject

Blocking; run it in a thread. Returns when the child closes the pty.



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
# File 'lib/everywhere/relay.rb', line 35

def run
  Console.tag = @source
  pump = LinePump.new
  loop do
    if @io.wait_readable(POLL)
      chunk = @io.read_nonblock(CHUNK, exception: false)
      break if chunk.nil? # EOF

      publish(pump << chunk) unless chunk == :wait_readable
    else
      publish(pump.flush_idle)
    end
  end
  publish(pump.drain)
rescue Errno::EIO, IOError, Errno::EBADF
  # A pty master raises EIO (not EOF) once the last slave closes, which is
  # simply how a child exiting looks from this side.
  publish(pump.drain) if pump
ensure
  @log&.close
  begin
    @io.close
  rescue StandardError
    nil
  end
end