feat: merge persistent route catalog into unified catalog endpoint

Wires RouteCatalogStore into CatalogController as a third data source:
routes with zero executions and routes from previous app versions
(within the queried time window) now appear in the unified catalog.
Also clears route_catalog on app dismiss via deleteByApplication().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-16 18:49:00 +02:00
parent 462b9a4bf0
commit 24c858cca4

View File

@@ -11,6 +11,8 @@ import com.cameleer.server.core.agent.AgentState;
import com.cameleer.server.core.agent.RouteStateRegistry; import com.cameleer.server.core.agent.RouteStateRegistry;
import com.cameleer.server.core.runtime.*; import com.cameleer.server.core.runtime.*;
import com.cameleer.server.core.storage.DiagramStore; import com.cameleer.server.core.storage.DiagramStore;
import com.cameleer.server.core.storage.RouteCatalogEntry;
import com.cameleer.server.core.storage.RouteCatalogStore;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -47,6 +49,7 @@ public class CatalogController {
private final EnvironmentService envService; private final EnvironmentService envService;
private final DeploymentRepository deploymentRepo; private final DeploymentRepository deploymentRepo;
private final TenantProperties tenantProperties; private final TenantProperties tenantProperties;
private final RouteCatalogStore routeCatalogStore;
@Value("${cameleer.server.catalog.discoveryttldays:7}") @Value("${cameleer.server.catalog.discoveryttldays:7}")
private int discoveryTtlDays; private int discoveryTtlDays;
@@ -58,7 +61,8 @@ public class CatalogController {
AppService appService, AppService appService,
EnvironmentService envService, EnvironmentService envService,
DeploymentRepository deploymentRepo, DeploymentRepository deploymentRepo,
TenantProperties tenantProperties) { TenantProperties tenantProperties,
RouteCatalogStore routeCatalogStore) {
this.registryService = registryService; this.registryService = registryService;
this.diagramStore = diagramStore; this.diagramStore = diagramStore;
this.jdbc = jdbc; this.jdbc = jdbc;
@@ -67,6 +71,7 @@ public class CatalogController {
this.envService = envService; this.envService = envService;
this.deploymentRepo = deploymentRepo; this.deploymentRepo = deploymentRepo;
this.tenantProperties = tenantProperties; this.tenantProperties = tenantProperties;
this.routeCatalogStore = routeCatalogStore;
} }
@GetMapping @GetMapping
@@ -154,6 +159,20 @@ public class CatalogController {
} }
} }
// Merge routes from persistent catalog (covers routes with 0 executions
// and routes from previous app versions within the selected time window)
try {
List<RouteCatalogEntry> catalogEntries = (environment != null && !environment.isBlank())
? routeCatalogStore.findByEnvironment(environment, rangeFrom, rangeTo)
: routeCatalogStore.findAll(rangeFrom, rangeTo);
for (RouteCatalogEntry entry : catalogEntries) {
routesByApp.computeIfAbsent(entry.applicationId(), k -> new LinkedHashSet<>())
.add(entry.routeId());
}
} catch (Exception e) {
log.warn("Failed to query route catalog: {}", e.getMessage());
}
// 7. Build unified catalog // 7. Build unified catalog
Set<String> allSlugs = new LinkedHashSet<>(appsBySlug.keySet()); Set<String> allSlugs = new LinkedHashSet<>(appsBySlug.keySet());
allSlugs.addAll(agentsByApp.keySet()); allSlugs.addAll(agentsByApp.keySet());
@@ -331,6 +350,7 @@ public class CatalogController {
// Delete ClickHouse data // Delete ClickHouse data
deleteClickHouseData(tenantId, applicationId); deleteClickHouseData(tenantId, applicationId);
routeCatalogStore.deleteByApplication(applicationId);
// Delete managed app if exists (PostgreSQL) // Delete managed app if exists (PostgreSQL)
try { try {
@@ -348,7 +368,7 @@ public class CatalogController {
String[] tablesWithAppId = { String[] tablesWithAppId = {
"executions", "processor_executions", "route_diagrams", "agent_events", "executions", "processor_executions", "route_diagrams", "agent_events",
"stats_1m_app", "stats_1m_route", "stats_1m_processor_type", "stats_1m_processor", "stats_1m_app", "stats_1m_route", "stats_1m_processor_type", "stats_1m_processor",
"stats_1m_processor_detail" "stats_1m_processor_detail", "route_catalog"
}; };
for (String table : tablesWithAppId) { for (String table : tablesWithAppId) {
try { try {