refactor(topology)!: rename node info revision

Replace the epoch/revision freshness tuple with nodeInfoRevision.

BREAKING CHANGE: topology API clients must use nodeInfoRevision;
nodeInfoFullRevision and nodeInfoFullRevisionEpoch are removed.
This commit is contained in:
2026-08-31 01:13:34 +08:00
parent 0b705f9ba0
commit 8c13af680a
3 changed files with 9 additions and 29 deletions
+3 -6
View File
@@ -14,8 +14,7 @@ export interface LayoutNode extends SimulationNodeDatum {
compressedAddress?: string
isSelf: boolean
deviceName?: string
nodeInfoFullRevision?: number
nodeInfoFullRevisionEpoch?: string
nodeInfoRevision?: number
x: number
y: number
}
@@ -121,8 +120,7 @@ export function useTopology(): UseTopologyResult {
(n) => n && typeof n.id === 'string' && n.id !== ''
).map((n) => ({
...n,
nodeInfoFullRevision: n.nodeInfoFullRevision ?? 0,
nodeInfoFullRevisionEpoch: n.nodeInfoFullRevisionEpoch ?? '',
nodeInfoRevision: n.nodeInfoRevision ?? 0,
}))
: []
const topoEdgesRaw: TopologyEdge[] = Array.isArray(payload.edges)
@@ -180,8 +178,7 @@ export function useTopology(): UseTopologyResult {
? {
...n,
deviceName: fresh.deviceName,
nodeInfoFullRevision: fresh.nodeInfoFullRevision,
nodeInfoFullRevisionEpoch: fresh.nodeInfoFullRevisionEpoch,
nodeInfoRevision: fresh.nodeInfoRevision,
}
: n
})
+5 -21
View File
@@ -17,22 +17,6 @@ import { TopologyCanvas } from '@/components/topology/topology-canvas'
import { NodeDetailSheet } from '@/components/topology/node-detail-sheet'
import type { NodeInfoDetail } from '@/types/api'
type NodeInfoFreshnessKey = readonly [epoch: string, revision: number]
function getNodeInfoFreshnessKey(node: {
nodeInfoFullRevision?: number
nodeInfoFullRevisionEpoch?: string
}): NodeInfoFreshnessKey {
return [node.nodeInfoFullRevisionEpoch ?? '', node.nodeInfoFullRevision ?? 0]
}
function freshnessKeysEqual(
left: NodeInfoFreshnessKey | null,
right: NodeInfoFreshnessKey
): boolean {
return left?.[0] === right[0] && left?.[1] === right[1]
}
export function TopologyPage() {
const { nodes, edges, isLoading, error, relayout } = useTopology()
const [searchQuery, setSearchQuery] = useState('')
@@ -44,7 +28,7 @@ export function TopologyPage() {
const [nodeInfo, setNodeInfo] = useState<NodeInfoDetail | null>(null)
const [nodeInfoLoading, setNodeInfoLoading] = useState(false)
const nodeInfoSeqRef = useRef(0)
const nodeInfoFreshnessRef = useRef<NodeInfoFreshnessKey | null>(null)
const nodeInfoRevisionRef = useRef<number | null>(null)
const nodeInfoRevisionInitializedRef = useRef(false)
const fetchNodeInfo = useCallback((nodeId: string) => {
@@ -73,7 +57,7 @@ export function TopologyPage() {
if (nodeId) {
setSheetOpen(true)
const selected = nodes.find((node) => node.id === nodeId)
nodeInfoFreshnessRef.current = getNodeInfoFreshnessKey(selected ?? {})
nodeInfoRevisionRef.current = selected?.nodeInfoRevision ?? 0
nodeInfoRevisionInitializedRef.current = true
fetchNodeInfo(nodeId)
} else {
@@ -101,10 +85,10 @@ export function TopologyPage() {
useEffect(() => {
if (!selectedNode) return
const freshnessKey = getNodeInfoFreshnessKey(selectedNode)
const nodeInfoRevision = selectedNode.nodeInfoRevision ?? 0
if (!nodeInfoRevisionInitializedRef.current) return
if (!freshnessKeysEqual(nodeInfoFreshnessRef.current, freshnessKey)) {
nodeInfoFreshnessRef.current = freshnessKey
if (nodeInfoRevisionRef.current !== nodeInfoRevision) {
nodeInfoRevisionRef.current = nodeInfoRevision
fetchNodeInfo(selectedNode.id)
}
}, [selectedNode, fetchNodeInfo])
+1 -2
View File
@@ -80,8 +80,7 @@ export interface TopologyNode {
compressedAddress?: string
isSelf: boolean
deviceName?: string
nodeInfoFullRevision?: number
nodeInfoFullRevisionEpoch?: string
nodeInfoRevision?: number
}
export interface TopologyEdge {