Class: Build::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/build/controller.rb

Overview

Represents the top-level build controller that manages the walker and process group.

Defined Under Namespace

Classes: Builder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nodes = [], limit: nil) ⇒ Controller

Initialize the controller, yielding self to allow adding chain nodes.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/build/controller.rb', line 50

def initialize(nodes = [], limit: nil)
  if block_given?
    warn "Passing a block to Build::Controller.new is deprecated, use Build::Controller.build instead."
    
    builder = Builder.new
    yield builder
    @nodes = builder.nodes.freeze
  else
    @nodes = nodes.freeze
  end
  
  @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

Instance Attribute Details

#nodesObject (readonly)

Returns the value of attribute nodes.



69
70
71
# File 'lib/build/controller.rb', line 69

def nodes
  @nodes
end

#walkerObject (readonly)

Returns the value of attribute walker.



70
71
72
# File 'lib/build/controller.rb', line 70

def walker
  @walker
end

Class Method Details

.build(**options) {|builder| ... } ⇒ Object

Create a new controller using a builder.

Yields:

  • (builder)


40
41
42
43
44
45
46
# File 'lib/build/controller.rb', line 40

def self.build(**options)
  builder = Builder.new
  
  yield builder
  
  new(builder.nodes, **options)
end

Instance Method Details

#failed?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/build/controller.rb', line 93

def failed?
  @walker.failed?
end

#runObject

The entry point for running the walker over the build graph.



108
109
110
111
112
113
114
# File 'lib/build/controller.rb', line 108

def run
  @walker.run do
    self.update
    
    yield @walker if block_given?
  end
end

#step(walker, node, parent_task = nil) ⇒ Object

Execute a single step of the build graph for the given node.



85
86
87
88
89
90
# File 'lib/build/controller.rb', line 85

def step(walker, node, parent_task = nil)
  task_class = node.task_class(parent_task) || Task
  task = task_class.new(walker, node, @group)
  
  self.visit(task)
end

#updateObject

Execute all top-level nodes, waiting for each to complete.



98
99
100
101
102
103
104
105
# File 'lib/build/controller.rb', line 98

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

#visit(task) ⇒ Object

Visit a task, executing its update method within the context of the task's visit method.



75
76
77
78
79
# File 'lib/build/controller.rb', line 75

def visit(task)
  task.visit do
    task.update
  end
end