fix: separate onException/errorHandler into distinct RouteFlow segments
ON_EXCEPTION and ERROR_HANDLER nodes are now treated as compound containers in the ELK diagram renderer, nesting their children. The frontend diagram-mapping builds separate FlowSegments for each error handler, displayed as distinct sections in the RouteFlow component. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import type { ProcessorStep, RouteNode, NodeBadge, LogEntry, ButtonGroupItem } f
|
||||
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions'
|
||||
import { useCorrelationChain } from '../../api/queries/correlation'
|
||||
import { useDiagramLayout } from '../../api/queries/diagrams'
|
||||
import { mapDiagramToRouteNodes, toFlowSegments } from '../../utils/diagram-mapping'
|
||||
import { buildFlowSegments, toFlowSegments } from '../../utils/diagram-mapping'
|
||||
import { useTracingStore } from '../../stores/tracing-store'
|
||||
import { useApplicationConfig, useUpdateApplicationConfig, useReplayExchange } from '../../api/queries/commands'
|
||||
import { useAgents } from '../../api/queries/agents'
|
||||
@@ -171,26 +171,30 @@ export default function ExchangeDetail() {
|
||||
const outputBody = snapshot?.outputBody ?? null
|
||||
|
||||
// Build RouteFlow nodes from diagram + execution data, split into flow segments
|
||||
const { routeFlows, flowIndexMap } = useMemo(() => {
|
||||
let nodes: RouteNode[]
|
||||
const { routeFlows, flowNodeIds } = useMemo(() => {
|
||||
if (diagram?.nodes) {
|
||||
// node.id is the processorId (Camel nodeId), so lookup is direct
|
||||
nodes = mapDiagramToRouteNodes(diagram.nodes, procList).map((node, i) => ({
|
||||
...node,
|
||||
badges: badgesFor(diagram.nodes[i]?.id ?? ''),
|
||||
}))
|
||||
} else {
|
||||
// Fallback: build from processor list
|
||||
nodes = processors.map((p) => ({
|
||||
name: p.name,
|
||||
type: 'process' as RouteNode['type'],
|
||||
durationMs: p.durationMs,
|
||||
status: p.status,
|
||||
badges: badgesFor(p.name),
|
||||
const { flows, nodeIds } = buildFlowSegments(diagram.nodes, procList)
|
||||
// Apply badges to each node across all flows
|
||||
let idx = 0
|
||||
const badgedFlows = flows.map(flow => ({
|
||||
...flow,
|
||||
nodes: flow.nodes.map(node => ({
|
||||
...node,
|
||||
badges: badgesFor(nodeIds[idx++]),
|
||||
})),
|
||||
}))
|
||||
return { routeFlows: badgedFlows, flowNodeIds: nodeIds }
|
||||
}
|
||||
const { flows, indexMap } = toFlowSegments(nodes)
|
||||
return { routeFlows: flows, flowIndexMap: indexMap }
|
||||
// Fallback: build from processor list (no diagram available)
|
||||
const nodes = processors.map((p) => ({
|
||||
name: p.name,
|
||||
type: 'process' as RouteNode['type'],
|
||||
durationMs: p.durationMs,
|
||||
status: p.status,
|
||||
badges: badgesFor(p.name),
|
||||
}))
|
||||
const { flows } = toFlowSegments(nodes)
|
||||
return { routeFlows: flows, flowNodeIds: [] as string[] }
|
||||
}, [diagram, processors, procList, tracedMap])
|
||||
|
||||
// ProcessorId lookup: timeline index → processorId
|
||||
@@ -204,19 +208,11 @@ export default function ExchangeDetail() {
|
||||
return ids
|
||||
}, [procList])
|
||||
|
||||
// ProcessorId lookup: diagram node index → processorId (node.id IS processorId)
|
||||
const flowProcessorIds: string[] = useMemo(() => {
|
||||
if (!diagram?.nodes) return processorIds
|
||||
return diagram.nodes.map(node => node.id ?? '')
|
||||
}, [diagram, processorIds])
|
||||
|
||||
// Map flow display index → processor tree index (for snapshot API)
|
||||
// flowNodeIds already contains processor IDs in flow-order
|
||||
const flowToTreeIndex = useMemo(() =>
|
||||
flowIndexMap.map(diagramIdx => {
|
||||
const pid = flowProcessorIds[diagramIdx]
|
||||
return pid ? processorIds.indexOf(pid) : -1
|
||||
}),
|
||||
[flowIndexMap, flowProcessorIds, processorIds],
|
||||
flowNodeIds.map(pid => pid ? processorIds.indexOf(pid) : -1),
|
||||
[flowNodeIds, processorIds],
|
||||
)
|
||||
|
||||
// ── Tracing toggle ──────────────────────────────────────────────────────
|
||||
@@ -496,8 +492,7 @@ export default function ExchangeDetail() {
|
||||
}}
|
||||
selectedIndex={flowToTreeIndex.indexOf(activeIndex)}
|
||||
getActions={(_node, index) => {
|
||||
const origIdx = flowIndexMap[index] ?? index
|
||||
const pid = flowProcessorIds[origIdx]
|
||||
const pid = flowNodeIds[index] ?? ''
|
||||
if (!pid || !detail?.applicationName) return []
|
||||
return [{
|
||||
label: tracingStore.isTraced(app, pid) ? 'Disable Tracing' : 'Enable Tracing',
|
||||
|
||||
Reference in New Issue
Block a user