Class: ActiveMatrix::AgentRegistry

Inherits:
Object
  • Object
show all
Includes:
Logging, Singleton
Defined in:
lib/active_matrix/agent_registry.rb

Overview

Thread-safe registry for managing running bot agents

Instance Method Summary collapse

Methods included from Logging

included, #logger, #logger=

Constructor Details

#initializeAgentRegistry

Returns a new instance of AgentRegistry.



12
13
14
15
# File 'lib/active_matrix/agent_registry.rb', line 12

def initialize
  @agents = Concurrent::Hash.new
  @mutex = Mutex.new
end

Instance Method Details

#allObject

Get all running agents



53
54
55
# File 'lib/active_matrix/agent_registry.rb', line 53

def all
  @agents.values
end

#all_instancesObject

Get all bot instances



63
64
65
# File 'lib/active_matrix/agent_registry.rb', line 63

def all_instances
  @agents.values.pluck(:instance)
end

#all_recordsObject

Get all agent records



58
59
60
# File 'lib/active_matrix/agent_registry.rb', line 58

def all_records
  @agents.values.pluck(:record)
end

#broadcastObject

Broadcast to all agents



89
90
91
92
93
94
95
# File 'lib/active_matrix/agent_registry.rb', line 89

def broadcast
  all_instances.each do |instance|
    yield instance
  rescue StandardError => e
    logger.error "Error broadcasting to agent: #{e.message}"
  end
end

#broadcast_to(selector) ⇒ Object

Broadcast to specific agents



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/active_matrix/agent_registry.rb', line 98

def broadcast_to(selector)
  agents = case selector
           when Symbol
             by_state(selector)
           when String
             by_name_pattern(selector)
           when Class
             by_class(selector)
           when Proc
             @agents.values.select { |entry| selector.call(entry[:record]) }
           else
             []
           end

  agents.each do |entry|
    yield entry[:instance]
  rescue StandardError => e
    logger.error "Error broadcasting to agent #{entry[:record].name}: #{e.message}"
  end
end

#by_class(bot_class) ⇒ Object

Get agents by bot class



78
79
80
81
# File 'lib/active_matrix/agent_registry.rb', line 78

def by_class(bot_class)
  class_name = bot_class.is_a?(Class) ? bot_class.name : bot_class.to_s
  @agents.values.select { |entry| entry[:record].bot_class == class_name }
end

#by_homeserver(homeserver) ⇒ Object

Get agents by homeserver



84
85
86
# File 'lib/active_matrix/agent_registry.rb', line 84

def by_homeserver(homeserver)
  @agents.values.select { |entry| entry[:record].homeserver == homeserver }
end

#by_state(state) ⇒ Object

Get agents by state



73
74
75
# File 'lib/active_matrix/agent_registry.rb', line 73

def by_state(state)
  @agents.values.select { |entry| entry[:record].state == state.to_s }
end

#clear!Object

Clear all agents (used for testing)



125
126
127
128
129
# File 'lib/active_matrix/agent_registry.rb', line 125

def clear!
  @mutex.synchronize do
    @agents.clear
  end
end

#countObject

Get count of running agents



120
121
122
# File 'lib/active_matrix/agent_registry.rb', line 120

def count
  @agents.size
end

#get(agent_id) ⇒ Object

Get a running agent by ID



43
44
45
# File 'lib/active_matrix/agent_registry.rb', line 43

def get(agent_id)
  @agents[agent_id]
end

#get_by_name(name) ⇒ Object

Get agent by name



48
49
50
# File 'lib/active_matrix/agent_registry.rb', line 48

def get_by_name(name)
  @agents.values.find { |entry| entry[:record].name == name }
end

#health_statusObject

Get health status of all agents



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/active_matrix/agent_registry.rb', line 132

def health_status
  @agents.map do |id, entry|
    {
      id: id,
      name: entry[:record].name,
      state: entry[:record].state,
      thread_alive: entry[:thread]&.alive?,
      uptime: Time.current - entry[:started_at],
      last_active: entry[:record].last_active_at
    }
  end
end

#register(agent_record, bot_instance) ⇒ Object

Register a running agent



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/active_matrix/agent_registry.rb', line 18

def register(agent_record, bot_instance)
  @mutex.synchronize do
    raise AgentAlreadyRunningError, "Agent #{agent_record.name} is already running" if @agents.key?(agent_record.id)

    @agents[agent_record.id] = {
      record: agent_record,
      instance: bot_instance,
      thread: Thread.current,
      started_at: Time.current
    }

    logger.info "Registered agent: #{agent_record.name} (#{agent_record.id})"
  end
end

#running?(agent_record) ⇒ Boolean

Check if an agent is running

Returns:

  • (Boolean)


68
69
70
# File 'lib/active_matrix/agent_registry.rb', line 68

def running?(agent_record)
  @agents.key?(agent_record.id)
end

#unregister(agent_record) ⇒ Object

Unregister an agent



34
35
36
37
38
39
40
# File 'lib/active_matrix/agent_registry.rb', line 34

def unregister(agent_record)
  @mutex.synchronize do
    entry = @agents.delete(agent_record.id)
    logger.info "Unregistered agent: #{agent_record.name} (#{agent_record.id})" if entry
    entry
  end
end