From 480a53c80ca6c47d0c0cefed9339b4d06c8a0d94 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:59:43 +0200 Subject: [PATCH] fix(diagrams): by-route lookup no longer requires live agents The env-scoped /routes/{routeId}/diagram endpoint filtered diagrams by the currently-live agent instance_ids. Routes removed between app versions have no live publisher, so the lookup returned 404 even though the historical diagram row still exists in route_diagrams. Sidebar entries for removed routes showed "no diagram" as a result. Switch to findLatestContentHashForAppRoute which resolves directly off (applicationId, environment, routeId) + created_at DESC, independent of the agent registry. The controller no longer depends on AgentRegistryService. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../controller/DiagramRenderController.java | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DiagramRenderController.java b/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DiagramRenderController.java index f8d576dd..6ed72f7c 100644 --- a/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DiagramRenderController.java +++ b/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DiagramRenderController.java @@ -2,8 +2,6 @@ package com.cameleer.server.app.controller; import com.cameleer.common.graph.RouteGraph; import com.cameleer.server.app.web.EnvPath; -import com.cameleer.server.core.agent.AgentInfo; -import com.cameleer.server.core.agent.AgentRegistryService; import com.cameleer.server.core.diagram.DiagramLayout; import com.cameleer.server.core.diagram.DiagramRenderer; import com.cameleer.server.core.runtime.Environment; @@ -21,7 +19,6 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.List; import java.util.Optional; /** @@ -42,14 +39,11 @@ public class DiagramRenderController { private final DiagramStore diagramStore; private final DiagramRenderer diagramRenderer; - private final AgentRegistryService registryService; public DiagramRenderController(DiagramStore diagramStore, - DiagramRenderer diagramRenderer, - AgentRegistryService registryService) { + DiagramRenderer diagramRenderer) { this.diagramStore = diagramStore; this.diagramRenderer = diagramRenderer; - this.registryService = registryService; } @GetMapping("/api/v1/diagrams/{contentHash}/render") @@ -90,8 +84,8 @@ public class DiagramRenderController { @GetMapping("/api/v1/environments/{envSlug}/apps/{appSlug}/routes/{routeId}/diagram") @Operation(summary = "Find the latest diagram for this app's route in this environment", - description = "Resolves agents in this env for this app, then looks up the latest diagram for the route " - + "they reported. Env scope prevents a dev route from returning a prod diagram.") + description = "Returns the most recently stored diagram for (app, env, route). Independent of the " + + "agent registry, so routes removed from the current app version still resolve.") @ApiResponse(responseCode = "200", description = "Diagram layout returned") @ApiResponse(responseCode = "404", description = "No diagram found") public ResponseEntity findByAppAndRoute( @@ -99,15 +93,7 @@ public class DiagramRenderController { @PathVariable String appSlug, @PathVariable String routeId, @RequestParam(defaultValue = "LR") String direction) { - List agentIds = registryService.findByApplicationAndEnvironment(appSlug, env.slug()).stream() - .map(AgentInfo::instanceId) - .toList(); - - if (agentIds.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - Optional contentHash = diagramStore.findContentHashForRouteByAgents(routeId, agentIds); + Optional contentHash = diagramStore.findLatestContentHashForAppRoute(appSlug, routeId, env.slug()); if (contentHash.isEmpty()) { return ResponseEntity.notFound().build(); }