package masterdb import ( "database/sql" "fmt" "time" ) // EdgeRoute records a public route managed by the master. type EdgeRoute struct { Hostname string ServiceName string EdgeNode string BackendHostname string BackendPort int CreatedAt time.Time } // CreateEdgeRoute inserts or replaces an edge route record. func CreateEdgeRoute(db *sql.DB, hostname, serviceName, edgeNode, backendHostname string, backendPort int) error { _, err := db.Exec(` INSERT INTO edge_routes (hostname, service_name, edge_node, backend_hostname, backend_port, created_at) VALUES (?, ?, ?, ?, ?, datetime('now')) ON CONFLICT(hostname) DO UPDATE SET service_name = excluded.service_name, edge_node = excluded.edge_node, backend_hostname = excluded.backend_hostname, backend_port = excluded.backend_port `, hostname, serviceName, edgeNode, backendHostname, backendPort) if err != nil { return fmt.Errorf("create edge route %s: %w", hostname, err) } return nil } // ListEdgeRoutes returns all edge routes. func ListEdgeRoutes(db *sql.DB) ([]*EdgeRoute, error) { return queryEdgeRoutes(db, `SELECT hostname, service_name, edge_node, backend_hostname, backend_port, created_at FROM edge_routes ORDER BY hostname`) } // ListEdgeRoutesForService returns edge routes for a specific service. func ListEdgeRoutesForService(db *sql.DB, serviceName string) ([]*EdgeRoute, error) { rows, err := db.Query(` SELECT hostname, service_name, edge_node, backend_hostname, backend_port, created_at FROM edge_routes WHERE service_name = ? ORDER BY hostname `, serviceName) if err != nil { return nil, fmt.Errorf("list edge routes for %s: %w", serviceName, err) } defer func() { _ = rows.Close() }() return scanEdgeRoutes(rows) } // DeleteEdgeRoute removes a single edge route by hostname. func DeleteEdgeRoute(db *sql.DB, hostname string) error { _, err := db.Exec(`DELETE FROM edge_routes WHERE hostname = ?`, hostname) if err != nil { return fmt.Errorf("delete edge route %s: %w", hostname, err) } return nil } // DeleteEdgeRoutesForService removes all edge routes for a service. func DeleteEdgeRoutesForService(db *sql.DB, serviceName string) error { _, err := db.Exec(`DELETE FROM edge_routes WHERE service_name = ?`, serviceName) if err != nil { return fmt.Errorf("delete edge routes for %s: %w", serviceName, err) } return nil } func queryEdgeRoutes(db *sql.DB, query string) ([]*EdgeRoute, error) { rows, err := db.Query(query) if err != nil { return nil, fmt.Errorf("query edge routes: %w", err) } defer func() { _ = rows.Close() }() return scanEdgeRoutes(rows) } func scanEdgeRoutes(rows *sql.Rows) ([]*EdgeRoute, error) { var routes []*EdgeRoute for rows.Next() { var r EdgeRoute var createdAt string if err := rows.Scan(&r.Hostname, &r.ServiceName, &r.EdgeNode, &r.BackendHostname, &r.BackendPort, &createdAt); err != nil { return nil, fmt.Errorf("scan edge route: %w", err) } r.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt) routes = append(routes, &r) } return routes, rows.Err() }