refactor: remove diagramNodeId indirection, use processorId directly
Agent now uses Camel processorId as RouteNode.id, eliminating the nodeId mapping layer. Drop diagram_node_id column (V6 migration), remove from ProcessorRecord/ProcessorNode/IngestionService/DetailService, add /processor-routes endpoint for processorId→routeId lookup, simplify frontend diagram-mapping and ExchangeDetail overlays, replace N diagram fetches in AppConfigPage with single hook. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,20 @@ export function useUpdateApplicationConfig() {
|
||||
})
|
||||
}
|
||||
|
||||
// ── Processor → Route Mapping ─────────────────────────────────────────────
|
||||
|
||||
export function useProcessorRouteMapping(application?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['config', application, 'processor-routes'],
|
||||
queryFn: async () => {
|
||||
const res = await authFetch(`/api/v1/config/${application}/processor-routes`)
|
||||
if (!res.ok) throw new Error('Failed to fetch processor-route mapping')
|
||||
return res.json() as Promise<Record<string, string>>
|
||||
},
|
||||
enabled: !!application,
|
||||
})
|
||||
}
|
||||
|
||||
// ── Generic Group Command (kept for non-config commands) ──────────────────
|
||||
|
||||
interface SendGroupCommandParams {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { useState, useMemo, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useQueries } from '@tanstack/react-query';
|
||||
import {
|
||||
DataTable, Badge, MonoText, DetailPanel, SectionHeader, Button, Toggle, Spinner, useToast,
|
||||
} from '@cameleer/design-system';
|
||||
import type { Column } from '@cameleer/design-system';
|
||||
import { useAllApplicationConfigs, useApplicationConfig, useUpdateApplicationConfig } from '../../api/queries/commands';
|
||||
import { useAllApplicationConfigs, useApplicationConfig, useUpdateApplicationConfig, useProcessorRouteMapping } from '../../api/queries/commands';
|
||||
import type { ApplicationConfig, TapDefinition } from '../../api/queries/commands';
|
||||
import { useRouteCatalog } from '../../api/queries/catalog';
|
||||
import { api } from '../../api/client';
|
||||
import type { AppCatalogEntry, RouteSummary } from '../../api/types';
|
||||
import styles from './AppConfigPage.module.css';
|
||||
|
||||
@@ -87,32 +85,8 @@ function AppConfigDetail({ appId, onClose }: { appId: string; onClose: () => voi
|
||||
return entry?.routes ?? [];
|
||||
}, [catalog, appId]);
|
||||
|
||||
// Fetch diagrams for all routes to build processorId → routeId mapping
|
||||
const diagramQueries = useQueries({
|
||||
queries: appRoutes.map((r) => ({
|
||||
queryKey: ['diagrams', 'byRoute', appId, r.routeId],
|
||||
queryFn: async () => {
|
||||
const { data, error } = await api.GET('/diagrams', {
|
||||
params: { query: { application: appId!, routeId: r.routeId } },
|
||||
});
|
||||
if (error) return { routeId: r.routeId, nodes: [] as Array<{ id?: string }> };
|
||||
return { routeId: r.routeId, nodes: (data as any)?.nodes ?? [] };
|
||||
},
|
||||
enabled: !!appId,
|
||||
staleTime: 60_000,
|
||||
})),
|
||||
});
|
||||
|
||||
const processorToRoute = useMemo(() => {
|
||||
const map: Record<string, string> = {};
|
||||
for (const q of diagramQueries) {
|
||||
if (!q.data) continue;
|
||||
for (const node of q.data.nodes) {
|
||||
if (node.id) map[node.id] = q.data.routeId;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}, [diagramQueries.map(q => q.data)]);
|
||||
// processorId → routeId mapping from backend
|
||||
const { data: processorToRoute = {} } = useProcessorRouteMapping(appId);
|
||||
|
||||
useEffect(() => {
|
||||
if (config) {
|
||||
|
||||
@@ -172,19 +172,10 @@ export default function ExchangeDetail() {
|
||||
const { routeFlows, flowIndexMap } = useMemo(() => {
|
||||
let nodes: RouteNode[]
|
||||
if (diagram?.nodes) {
|
||||
// Flatten processors to build diagramNodeId → processorId lookup
|
||||
const flatProcs: Array<{ diagramNodeId?: string; processorId?: string }> = []
|
||||
function flattenProcs(list: any[]) {
|
||||
for (const n of list) { flatProcs.push(n); if (n.children) flattenProcs(n.children) }
|
||||
}
|
||||
flattenProcs(procList)
|
||||
const pidLookup = new Map(flatProcs
|
||||
.filter(p => p.diagramNodeId && p.processorId)
|
||||
.map(p => [p.diagramNodeId!, p.processorId!]))
|
||||
|
||||
// node.id is the processorId (Camel nodeId), so lookup is direct
|
||||
nodes = mapDiagramToRouteNodes(diagram.nodes, procList).map((node, i) => ({
|
||||
...node,
|
||||
badges: badgesFor(pidLookup.get(diagram.nodes[i]?.id ?? '') ?? diagram.nodes[i]?.id ?? ''),
|
||||
badges: badgesFor(diagram.nodes[i]?.id ?? ''),
|
||||
}))
|
||||
} else {
|
||||
// Fallback: build from processor list
|
||||
@@ -211,22 +202,11 @@ export default function ExchangeDetail() {
|
||||
return ids
|
||||
}, [procList])
|
||||
|
||||
// ProcessorId lookup: diagram node index → processorId
|
||||
// ProcessorId lookup: diagram node index → processorId (node.id IS processorId)
|
||||
const flowProcessorIds: string[] = useMemo(() => {
|
||||
if (!diagram?.nodes) return processorIds
|
||||
const flatProcs: Array<{ diagramNodeId?: string; processorId?: string }> = []
|
||||
function flatten(nodes: any[]) {
|
||||
for (const n of nodes) {
|
||||
flatProcs.push(n)
|
||||
if (n.children) flatten(n.children)
|
||||
}
|
||||
}
|
||||
flatten(procList)
|
||||
const lookup = new Map(flatProcs
|
||||
.filter(p => p.diagramNodeId && p.processorId)
|
||||
.map(p => [p.diagramNodeId!, p.processorId!]))
|
||||
return diagram.nodes.map(node => lookup.get(node.id ?? '') ?? node.id ?? '')
|
||||
}, [diagram, procList, processorIds])
|
||||
return diagram.nodes.map(node => node.id ?? '')
|
||||
}, [diagram, processorIds])
|
||||
|
||||
// Map flow display index → processor tree index (for snapshot API)
|
||||
const flowToTreeIndex = useMemo(() =>
|
||||
|
||||
@@ -20,11 +20,11 @@ function mapStatus(status: string | undefined): RouteNode['status'] {
|
||||
|
||||
/**
|
||||
* Maps diagram PositionedNodes + execution ProcessorNodes to RouteFlow RouteNode[] format.
|
||||
* Joins on diagramNodeId → node.id.
|
||||
* Joins on processorId → node.id (node IDs are Camel processor IDs).
|
||||
*/
|
||||
export function mapDiagramToRouteNodes(
|
||||
diagramNodes: Array<{ id?: string; label?: string; type?: string }>,
|
||||
processors: Array<{ diagramNodeId?: string; processorId?: string; status?: string; durationMs?: number; children?: any[] }>
|
||||
processors: Array<{ processorId?: string; status?: string; durationMs?: number; children?: any[] }>
|
||||
): RouteNode[] {
|
||||
// Flatten processor tree
|
||||
const flatProcessors: typeof processors = [];
|
||||
@@ -36,10 +36,10 @@ export function mapDiagramToRouteNodes(
|
||||
}
|
||||
flatten(processors || []);
|
||||
|
||||
// Build lookup: diagramNodeId → processor
|
||||
// Build lookup: processorId → processor
|
||||
const procMap = new Map<string, (typeof flatProcessors)[0]>();
|
||||
for (const p of flatProcessors) {
|
||||
if (p.diagramNodeId) procMap.set(p.diagramNodeId, p);
|
||||
if (p.processorId) procMap.set(p.processorId, p);
|
||||
}
|
||||
|
||||
return diagramNodes.map(node => {
|
||||
|
||||
Reference in New Issue
Block a user