class Build::Graph::Task
Attributes
The error, if the execution of the node fails.
A list of any inputs whose relevant tasks failed:
The state of the task, one of nil, :complete or :failed.
Public Class Methods
# 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
# File lib/build/graph/task.rb, line 145 def changed! @walker.delete(@node) if (@inputs.update! or @outputs.update!) end
# File lib/build/graph/task.rb, line 131 def complete? @state == :complete end
# File lib/build/graph/task.rb, line 149 def directories (@inputs.roots + @outputs.roots).collect{|path| path.to_s} end
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
# File lib/build/graph/task.rb, line 127 def failed? @state == :failed end
# File lib/build/graph/task.rb, line 157 def inspect "\#<#{self.class}:0x#{self.object_id.to_s(16)} #{node_string} #{state_string}>" end
@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
# File lib/build/graph/task.rb, line 153 def to_s "#<#{self.class} #{node_string} #{state_string}>" end
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
@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 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
# File lib/build/graph/task.rb, line 183 def node_string @node.inspect end
# File lib/build/graph/task.rb, line 173 def state_string if @state @state.to_s elsif @fiber "running" else "new" end end
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
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
# File lib/build/graph/task.rb, line 163 def wait_for_children! unless wait_for_children? fail!(ChildrenFailed) return false end return true end
@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
@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