Class: RubyReactor::DependencyGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_reactor/dependency_graph.rb

Instance Method Summary collapse

Constructor Details

#initializeDependencyGraph

Returns a new instance of DependencyGraph.



5
6
7
8
9
10
# File 'lib/ruby_reactor/dependency_graph.rb', line 5

def initialize
  @nodes = {}
  @edges = {}
  @dependencies = {} # Store dependencies for each step
  @completed = Set.new
end

Instance Method Details

#add_dependency(step_name, dependency_name) ⇒ Object



38
39
40
41
# File 'lib/ruby_reactor/dependency_graph.rb', line 38

def add_dependency(step_name, dependency_name)
  @edges[dependency_name] ||= Set.new
  @edges[dependency_name] << step_name
end

#add_step(step_config) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ruby_reactor/dependency_graph.rb', line 12

def add_step(step_config)
  step_name = step_config.name
  @nodes[step_name] = step_config
  @edges[step_name] = Set.new

  # Calculate and store dependencies
  dependencies = []

  # Add dependencies from argument sources
  step_config.arguments.each_value do |arg_config|
    source = arg_config[:source]
    if source.is_a?(RubyReactor::Template::Result)
      dependencies << source.step_name
      add_dependency(step_name, source.step_name)
    end
  end

  # Add explicit dependencies
  step_config.dependencies.each do |dep_step|
    dependencies << dep_step
    add_dependency(step_name, dep_step)
  end

  @dependencies[step_name] = dependencies.uniq
end

#all_completed?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/ruby_reactor/dependency_graph.rb', line 86

def all_completed?
  @completed.size == @nodes.size
end

#complete_step(step_name) ⇒ Object



55
56
57
# File 'lib/ruby_reactor/dependency_graph.rb', line 55

def complete_step(step_name)
  @completed << step_name
end

#has_cycles?Boolean

Returns:

  • (Boolean)


59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ruby_reactor/dependency_graph.rb', line 59

def has_cycles?
  visited = Set.new
  rec_stack = Set.new

  @nodes.each_key do |node|
    next if visited.include?(node)
    return true if cycle_detected?(node, visited, rec_stack)
  end

  false
end

#pending_stepsObject



90
91
92
# File 'lib/ruby_reactor/dependency_graph.rb', line 90

def pending_steps
  @nodes.keys - @completed.to_a
end

#ready_stepsObject



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ruby_reactor/dependency_graph.rb', line 43

def ready_steps
  ready = []
  @nodes.each do |step_name, step_config|
    next if @completed.include?(step_name)

    # Check if all dependencies are completed
    dependencies = @dependencies[step_name] || []
    ready << step_config if dependencies.all? { |dep| @completed.include?(dep) }
  end
  ready
end

#topological_sortObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby_reactor/dependency_graph.rb', line 71

def topological_sort
  return [] if has_cycles?

  visited = Set.new
  stack = []

  @nodes.each_key do |node|
    next if visited.include?(node)

    topological_sort_util(node, visited, stack)
  end

  stack.reverse.map { |name| @nodes[name] }
end

#topological_sort_util(node, visited, stack) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ruby_reactor/dependency_graph.rb', line 94

def topological_sort_util(node, visited, stack)
  visited << node

  dependents = @edges[node] || Set.new
  dependents.each do |dependent|
    next if visited.include?(dependent)

    topological_sort_util(dependent, visited, stack)
  end

  stack << node
end