class Build::Graph::Task

Attributes

children[R]
error[R]

The error, if the execution of the node fails.

inputs[R]
inputs_failed[R]

A list of any inputs whose relevant tasks failed:

node[R]
outputs[R]
state[R]

The state of the task, one of nil, :complete or :failed.

walker[R]

Public Class Methods

new(walker, node) click to toggle source
# File lib/build/graph/task.rb, line 39
def initialize(walker, node)
        @walker = walker
        
        @walker.tasks[node] = self
        
        @node = node
        @fiber = nil
        
        @error = nil
        
        # Tasks that must be complete before finishing this task.
        @children = []
        
        @state = nil
        
        @inputs_failed = false
end

Public Instance Methods

changed!() click to toggle source
# File lib/build/graph/task.rb, line 145
def changed!
        @walker.delete(@node) if (@inputs.update! or @outputs.update!)
end
complete?() click to toggle source
# File lib/build/graph/task.rb, line 131
def complete?
        @state == :complete
end
directories() click to toggle source
# File lib/build/graph/task.rb, line 149
def directories
        (@inputs.roots + @outputs.roots).collect{|path| path.to_s}
end
dirty?() click to toggle source

Returns true if the outputs of the task are out of date w.r.t. the inputs. Currently, does not take into account if the input is a glob and files have been added.

# File lib/build/graph/task.rb, line 137
def dirty?
        if @outputs
                @outputs.dirty?(@inputs)
        else
                true
        end
end
failed?() click to toggle source
# File lib/build/graph/task.rb, line 127
def failed?
        @state == :failed
end
inspect() click to toggle source
# File lib/build/graph/task.rb, line 157
def inspect
        "\#<#{self.class}:0x#{self.object_id.to_s(16)} #{node_string} #{state_string}>"
end
invoke(node) click to toggle source

@return [Task] the child task that was created to update the node.

# File lib/build/graph/task.rb, line 117
def invoke(node)
        child_task = @walker.call(node, self)
        
        raise ArgumentError.new("Invalid child task") unless child_task
        
        @children << child_task
        
        return child_task
end
to_s() click to toggle source
# File lib/build/graph/task.rb, line 153
def to_s
        "#<#{self.class} #{node_string} #{state_string}>"
end
visit() { || ... } click to toggle source

Derived task can override this function to provide appropriate behaviour.

# File lib/build/graph/task.rb, line 76
def visit
        update_inputs_and_outputs
        
        # Inforn the walker a new task is being generated for this node:
        @walker.enter(self)
        
        if @fiber
                raise RuntimeError, "Task is already running!"
        end
        
        @fiber = Fiber.new do
                # If all inputs were good, we can update the node.
                if wait_for_inputs?
                        begin
                                yield
                        rescue TransientError => error
                                fail!(error)
                        end
                else
                        fail!(InputsFailed)
                end
                
                wait_for_children!
                
                update_outputs!
                
                @state ||= :complete
                
                @walker.exit(self)
                
                @fiber = nil
        end
        
        # Schedule the work, hopefully synchronously:
        @fiber.resume
        
        # This allows the child task to be passed back to the parent when it is first invoked.
        return self
end

Protected Instance Methods

children_outputs() click to toggle source

@return [Build::Files::List] the merged list of all children outputs.

# File lib/build/graph/task.rb, line 197
def children_outputs
        @children.collect(&:outputs).inject(Files::Paths::NONE, &:+)
end
fail!(error) click to toggle source

Fail the task with the given error. Any task which is waiting on this task will also fail (eventually).

# File lib/build/graph/task.rb, line 212
def fail!(error)
        @walker.logger&.error(self) {error}
        
        @error = error
        @state = :failed
end
node_string() click to toggle source
# File lib/build/graph/task.rb, line 183
def node_string
        @node.inspect
end
state_string() click to toggle source
# File lib/build/graph/task.rb, line 173
def state_string
        if @state
                @state.to_s
        elsif @fiber
                "running"
        else
                "new"
        end
end
update_inputs_and_outputs() click to toggle source

If the node inputs is a glob, this part of the process converts the glob into an actual list of files. If we are not inheriting outputs from children tasks, update our outputs now.

# File lib/build/graph/task.rb, line 188
def update_inputs_and_outputs
        @inputs = Files::State.new(@node.inputs)
        
        unless @node.inherit_outputs?
                @outputs = Files::State.new(@node.outputs)
        end
end
update_outputs!() click to toggle source

If the node's outputs were a glob, this checks the filesystem to figure out what files were actually generated. If it inherits the outputs of the child tasks, merge them into our own outputs.

# File lib/build/graph/task.rb, line 202
def update_outputs!
        if @node.inherit_outputs?
                @outputs = Files::State.new(self.children_outputs)
        else
                # After the task has finished, we update the output states:
                @outputs.update!
        end
end
wait_for_children!() click to toggle source
# File lib/build/graph/task.rb, line 163
def wait_for_children!
        unless wait_for_children?
                fail!(ChildrenFailed)
                
                return false
        end
        
        return true
end
wait_for_children?() click to toggle source

@return [Boolean] if all children succeeded.

# File lib/build/graph/task.rb, line 232
def wait_for_children?
        if @children&.any?
                unless @walker.wait_for_children(self, @children)
                        return false
                end
        end
        
        return true
end
wait_for_inputs?() click to toggle source

@return [Boolean] if all inputs succeeded.

# File lib/build/graph/task.rb, line 220
def wait_for_inputs?
        # Wait on any inputs, returns whether any inputs failed:
        if @inputs&.any?
                unless @walker.wait_on_paths(self, @inputs)
                        return false
                end
        end
        
        return true
end