Steepコードリーディング(3日目)
次回の続き、Steep::Drivers::Check#run
の Server::WorkerProcess.start_typecheck_workers
を追っていく。
Server::WorkerProcess
Server::WorkerProcess#.start_typecheck_workers
Etc.nprocessors
は有効なCPUコア数を返す。コア数に応じて並列処理してるという感じかな。
def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max || raise, delay_shutdown: false)
count.times.map do |i|
start_worker(
:typecheck,
name: "typecheck@#{i}",
steepfile: steepfile,
steep_command: steep_command,
index: [count, i],
patterns: args,
delay_shutdown: delay_shutdown,
)
end
end
Server::WorkerProcess#.start_worker
ターミナルから $ bundle exec steep check
を実行してる場合、steep_command
には"steep"
があるはずなので、spawn_worker
が実行される。
def self.start_worker(type, name:, steepfile:, steep_command:, index: nil, delay_shutdown: false, patterns: [])
begin
unless steep_command
fork_worker(
type,
name: name,
steepfile: steepfile,
index: index,
delay_shutdown: delay_shutdown,
patterns: patterns
)
else
# Use `#spawn_worker`
raise NotImplementedError
end
rescue NotImplementedError
spawn_worker(
type,
name: name,
steepfile: steepfile,
steep_command: steep_command || "steep",
index: index,
delay_shutdown: delay_shutdown,
patterns: patterns
)
end
end
Server::WorkerProcess#.spawn_worker
type
引数には :typecheck
が渡っているため、command
は["steep", "worker", "--typecheck", "--name=typecheck@1", "--steepfile=Steepfile", "--log-level=error", "--max-index=1", "--index=1", "--delay-shutdown"]
こんな感じになりそう。
自分の環境はWindowsではないので stdin, stdout, thread = Open3.popen2(*command, pgroup: true)
となりそう。Open3.popen2
とはこれ。
def self.spawn_worker(type, name:, steepfile:, steep_command:, index:, delay_shutdown:, patterns:)
args = ["--name=#{name}"]
args << "--steepfile=#{steepfile}" if steepfile
args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
if Steep.log_output.is_a?(String)
args << "--log-output=#{Steep.log_output}"
end
if (max, this = index)
args << "--max-index=#{max}"
args << "--index=#{this}"
end
if delay_shutdown
args << "--delay-shutdown"
end
command = case type
when :interaction
[steep_command, "worker", "--interaction", *args, *patterns]
when :typecheck
[steep_command, "worker", "--typecheck", *args, *patterns]
else
raise "Unknown type: #{type}"
end
stdin, stdout, thread = if Gem.win_platform?
__skip__ = Open3.popen2(*command, new_pgroup: true)
else
__skip__ = Open3.popen2(*command, pgroup: true)
end
stderr = nil
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
end