Files
AetherForge/server/internal/db/agents_list.go

86 lines
2.3 KiB
Go

package db
import (
"fmt"
"strings"
"crypto-miner-server/internal/models"
)
// AgentListFilter holds optional filters for paginated agent queries.
type AgentListFilter struct {
Limit int // 0 = no limit (return all matching rows)
Offset int
Status string // "online", "offline", or "" for any
Subnet string // e.g. "10.0.0.x" — matched against agents.ip prefix
}
// subnetToIPPrefix converts UI subnet labels to SQL LIKE patterns.
func subnetToIPPrefix(subnet string) string {
subnet = strings.TrimSpace(subnet)
if subnet == "" {
return ""
}
if strings.HasSuffix(subnet, ".x") {
return strings.TrimSuffix(subnet, ".x") + ".%"
}
if strings.HasSuffix(subnet, "%") {
return subnet
}
parts := strings.Split(subnet, ".")
if len(parts) >= 3 {
return fmt.Sprintf("%s.%s.%s.%%", parts[0], parts[1], parts[2])
}
return subnet + "%"
}
func (d *Database) agentListWhere(f AgentListFilter) (clause string, args []interface{}) {
var where []string
if f.Status != "" {
where = append(where, "status = ?")
args = append(args, f.Status)
}
if prefix := subnetToIPPrefix(f.Subnet); prefix != "" {
where = append(where, "ip LIKE ?")
args = append(args, prefix)
}
if len(where) == 0 {
return "", nil
}
return " WHERE " + strings.Join(where, " AND "), args
}
// ListAgentsFiltered returns agents matching optional status/subnet filters.
// When Limit > 0, results are paginated with Offset.
func (d *Database) ListAgentsFiltered(f AgentListFilter) ([]*models.Agent, error) {
where, args := d.agentListWhere(f)
query := `SELECT ` + agentSelectCols + ` FROM agents` + where + ` ORDER BY last_seen DESC`
if f.Limit > 0 {
query += ` LIMIT ? OFFSET ?`
args = append(args, f.Limit, f.Offset)
}
rows, err := d.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var agents []*models.Agent
for rows.Next() {
a, err := d.scanAgent(rows)
if err != nil {
return nil, err
}
agents = append(agents, a)
}
return agents, rows.Err()
}
// CountAgentsFiltered returns the number of agents matching filter criteria (ignores Limit/Offset).
func (d *Database) CountAgentsFiltered(f AgentListFilter) (int, error) {
where, args := d.agentListWhere(f)
var n int
err := d.QueryRow(`SELECT COUNT(*) FROM agents`+where, args...).Scan(&n)
return n, err
}