class Controller
Represents the top-level build controller that manages the walker and process group.
Definitions
def initialize(limit: nil)
Initialize the controller, yielding self to allow adding chain nodes.
Signature
-
parameter
limitInteger | Nil Maximum number of concurrent processes.
Implementation
def initialize(limit: nil)
@module = Module.new
# Top level nodes, for sanity this is a static list.
@nodes = []
yield self
@nodes.freeze
@group = Process::Group.new(limit: limit)
# The task class is captured as we traverse all the top level targets:
@task_class = nil
@walker = Graph::Walker.new(&self.method(:step))
end
def step(walker, node, parent_task = nil)
Execute a single step of the build graph for the given node.
Signature
-
parameter
walkerBuild::Graph::Walker The graph walker.
-
parameter
nodeBuild::Graph::Node The node to process.
-
parameter
parent_taskBuild::Task | Nil The parent task, if any.
Implementation
def step(walker, node, parent_task = nil)
task_class = node.task_class(parent_task) || Task
task = task_class.new(walker, node, @group)
task.visit do
task.update
end
end
def failed?
Signature
-
returns
Boolean Whether the build has failed.
Implementation
def failed?
@walker.failed?
end
def add_chain(chain, arguments = [], environment)
Add a build environment to the controller.
Implementation
def add_chain(chain, arguments = [], environment)
@nodes << ChainNode.new(chain, arguments, environment)
end
def update
Execute all top-level nodes, waiting for each to complete.
Implementation
def update
@nodes.each do |node|
# We wait for all processes to complete within each node. The result is that we don't execute top level nodes concurrently, but we do execute within each node concurrently where possible. Ideally, some node could be executed concurrently, but right now expressing non-file dependencies between nodes is not possible.
@group.wait do
@walker.call(node)
end
end
end
def run
The entry point for running the walker over the build graph.
Implementation
def run
@walker.run do
self.update
yield @walker if block_given?
end
end