Class: Legion::Extensions::Agentic::Executive::LoadBalancing::Helpers::LoadBalancer

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb

Constant Summary

Constants included from Constants

Constants::DEFAULT_CAPACITY, Constants::HEALTH_LABELS, Constants::LOAD_LABELS, Constants::MAX_SUBSYSTEMS, Constants::MAX_TASKS, Constants::OVERLOAD_THRESHOLD, Constants::REBALANCE_STEP, Constants::SUBSYSTEM_TYPES, Constants::UNDERLOAD_THRESHOLD

Instance Method Summary collapse

Constructor Details

#initializeLoadBalancer

Returns a new instance of LoadBalancer.



12
13
14
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 12

def initialize
  @subsystems = {}
end

Instance Method Details

#assign_load(subsystem_id:, amount:) ⇒ Object



27
28
29
30
31
32
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 27

def assign_load(subsystem_id:, amount:)
  subsystem = @subsystems[subsystem_id]
  return nil unless subsystem

  subsystem.add_load!(amount: amount)
end

#auto_assign(amount:, subsystem_type: nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 41

def auto_assign(amount:, subsystem_type: nil)
  candidates = if subsystem_type
                 @subsystems.values.select { |s| s.subsystem_type == subsystem_type.to_sym }
               else
                 @subsystems.values
               end
  return nil if candidates.empty?

  best = candidates.min_by(&:utilization)
  best.add_load!(amount: amount)
  best
end

#balance_reportObject



103
104
105
106
107
108
109
110
111
112
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 103

def balance_report
  {
    total_subsystems:    @subsystems.size,
    overloaded_count:    overloaded_subsystems.size,
    underloaded_count:   underloaded_subsystems.size,
    overall_utilization: overall_utilization,
    overall_health:      overall_health,
    most_loaded:         most_loaded(limit: 3).map(&:to_h)
  }
end

#most_loaded(limit: 5) ⇒ Object



85
86
87
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 85

def most_loaded(limit: 5)
  @subsystems.values.sort_by { |s| -s.utilization }.first(limit)
end

#overall_healthObject



96
97
98
99
100
101
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 96

def overall_health
  return 1.0 if @subsystems.empty?

  healths = @subsystems.values.map(&:health)
  (healths.sum / healths.size).round(10)
end

#overall_utilizationObject



89
90
91
92
93
94
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 89

def overall_utilization
  return 0.0 if @subsystems.empty?

  utils = @subsystems.values.map(&:utilization)
  (utils.sum / utils.size).round(10)
end

#overloaded_subsystemsObject



72
73
74
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 72

def overloaded_subsystems
  @subsystems.values.select(&:overloaded?)
end

#rebalanceObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 54

def rebalance
  overloaded = @subsystems.values.select(&:overloaded?)
  underloaded = @subsystems.values.select(&:underloaded?)
  transfers = 0

  overloaded.each do |over|
    target = underloaded.min_by(&:utilization)
    break unless target

    transfer_amount = [REBALANCE_STEP, over.current_load * 0.2].min
    shed = over.shed_load!(amount: transfer_amount)
    target.add_load!(amount: shed)
    transfers += 1
  end

  transfers
end

#register_subsystem(name:, subsystem_type: :general, capacity: DEFAULT_CAPACITY) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 16

def register_subsystem(name:, subsystem_type: :general, capacity: DEFAULT_CAPACITY)
  prune_if_needed
  subsystem = Subsystem.new(
    name:           name,
    subsystem_type: subsystem_type,
    capacity:       capacity
  )
  @subsystems[subsystem.id] = subsystem
  subsystem
end

#shed_load(subsystem_id:, amount:) ⇒ Object



34
35
36
37
38
39
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 34

def shed_load(subsystem_id:, amount:)
  subsystem = @subsystems[subsystem_id]
  return nil unless subsystem

  subsystem.shed_load!(amount: amount)
end

#subsystems_by_type(subsystem_type:) ⇒ Object



80
81
82
83
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 80

def subsystems_by_type(subsystem_type:)
  st = subsystem_type.to_sym
  @subsystems.values.select { |s| s.subsystem_type == st }
end

#to_hObject



114
115
116
117
118
119
120
121
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 114

def to_h
  {
    total_subsystems:    @subsystems.size,
    overall_utilization: overall_utilization,
    overall_health:      overall_health,
    overloaded_count:    overloaded_subsystems.size
  }
end

#underloaded_subsystemsObject



76
77
78
# File 'lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb', line 76

def underloaded_subsystems
  @subsystems.values.select(&:underloaded?)
end