From 49dfaa77e63faa4c772d12411177351dcb39deee Mon Sep 17 00:00:00 2001 From: dtoro Date: Tue, 14 Jul 2026 22:02:58 +0200 Subject: [PATCH] fix(api): sort graph nodes by degree instead of alphabetically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unrooted graph endpoint caps at 500 entities with ORDER BY e.slug, which fills the cap with exec:* rows and excludes every host/lxc/service/vm entity. Since edges require both endpoints in the node set (ANY/ANY), 99.9% of edges were dropped — 500 nodes but only 1 edge survived. Fix: select the 500 most-connected entities (by relationship count descending) so the topology is preserved. Result: 500 nodes, 900 edges across all relationship types. --- VERSION | 2 +- internal/httpapi/impl.go | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index be14282..7d85683 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.3 +0.5.4 diff --git a/internal/httpapi/impl.go b/internal/httpapi/impl.go index b07fcb1..0074011 100644 --- a/internal/httpapi/impl.go +++ b/internal/httpapi/impl.go @@ -304,10 +304,24 @@ func (s *Server) GetGraph(ctx context.Context, req gen.GetGraphRequestObject) (g LEFT JOIN entity_status st ON st.entity_id = e.id ORDER BY e.slug`, rootID, depth, req.Params.RelType) } else { + // Whole-graph view: pick the most-connected entities first so the + // graph shows actual topology, not just whatever sorts first + // alphabetically. Without this the cap fills with exec:* rows and + // drops every host/lxc/service/vm — and every edge those entities + // connect — because edges require both endpoints in the node set. nodes, err = s.queryEntities(ctx, ` - SELECT `+entityCols+` FROM entities e + SELECT `+entityCols+` + FROM entities e LEFT JOIN entity_status st ON st.entity_id = e.id - ORDER BY e.slug LIMIT $1`, + WHERE e.id IN ( + SELECT e2.id FROM entities e2 + LEFT JOIN relationships r ON r.valid_to IS NULL + AND (r.source_id = e2.id OR r.target_id = e2.id) + GROUP BY e2.id + ORDER BY count(r.type) DESC, e2.slug + LIMIT $1 + ) + ORDER BY e.slug`, graphNodeCap+1) if err == nil && len(nodes) > graphNodeCap { nodes = nodes[:graphNodeCap]