package store import ( "errors" "log/slog" "sync" "time" "nerd-monitor/internal/stats" ) var ( // ErrAgentNotFound is returned when an agent is not found. ErrAgentNotFound = errors.New("agent not found") ) // AgentStats represents the latest stats for an agent. type AgentStats struct { ID string Hostname string CPUUsage float64 RAMUsage uint64 RAMTotal uint64 DiskUsage uint64 DiskTotal uint64 LastSeen time.Time } // Store manages agent statistics in memory. type Store struct { mu sync.RWMutex agents map[string]*AgentStats } // New creates a new store. func New() *Store { return &Store{ agents: make(map[string]*AgentStats), } } // UpdateAgent updates or creates agent stats. func (s *Store) UpdateAgent(id string, stat *stats.Stats) { s.mu.Lock() defer s.mu.Unlock() s.agents[id] = &AgentStats{ ID: id, Hostname: stat.Hostname, CPUUsage: stat.CPUUsage, RAMUsage: stat.RAMUsage, RAMTotal: stat.RAMTotal, DiskUsage: stat.DiskUsage, DiskTotal: stat.DiskTotal, LastSeen: time.Now(), } slog.Debug("Agent stats updated", "agentID", id, "hostname", stat.Hostname, "cpu", stat.CPUUsage) } // GetAgent retrieves agent stats by ID. func (s *Store) GetAgent(id string) *AgentStats { s.mu.RLock() defer s.mu.RUnlock() agent := s.agents[id] if agent != nil { slog.Debug("Agent retrieved", "agentID", id, "hostname", agent.Hostname) } else { slog.Debug("Agent not found", "agentID", id) } return agent } // GetAllAgents returns all agents. func (s *Store) GetAllAgents() []*AgentStats { s.mu.RLock() defer s.mu.RUnlock() agents := make([]*AgentStats, 0, len(s.agents)) for _, agent := range s.agents { agents = append(agents, agent) } slog.Debug("All agents retrieved", "count", len(agents)) return agents } // DeleteAgent removes an agent. func (s *Store) DeleteAgent(id string) { s.mu.Lock() defer s.mu.Unlock() delete(s.agents, id) slog.Debug("Agent deleted", "agentID", id) } // UpdateHostname updates the hostname for an agent. func (s *Store) UpdateHostname(id string, hostname string) error { s.mu.Lock() defer s.mu.Unlock() agent, exists := s.agents[id] if !exists { slog.Debug("Agent not found for hostname update", "agentID", id) return ErrAgentNotFound } agent.Hostname = hostname slog.Debug("Agent hostname updated", "agentID", id, "hostname", hostname) return nil }