Discard late Fleet history replies after changing selected node

This commit is contained in:
archipelago
2026-10-06 06:54:46 -04:00
parent a0cb29744d
commit cb33fe26e4
2 changed files with 31 additions and 2 deletions
@@ -46,3 +46,25 @@ it('does not rearm timers when requests finish after unmount', async () => {
expect(intervals).toHaveBeenCalledTimes(intervalCalls) expect(intervals).toHaveBeenCalledTimes(intervalCalls)
intervals.mockRestore(); clear.mockRestore() intervals.mockRestore(); clear.mockRestore()
}) })
it('keeps a late node history response out of the newly selected node', async () => {
const history = new Map<string, (value: unknown) => void>()
vi.mocked(rpcClient.call).mockImplementation(({ method, params }) => {
if (method === 'telemetry.fleet-node-history') return new Promise(done => { history.set((params as { node_id: string }).node_id, done) }) as never
return Promise.resolve({ nodes: [], alerts: [] }) as never
})
let fleet!: ReturnType<typeof useFleetData>
const wrapper = mount(defineComponent({ setup() { fleet = useFleetData(); return () => null } }))
await flushPromises()
fleet.selectNode('first'); await flushPromises()
fleet.selectNode('second'); await flushPromises()
history.get('first')!({ history: [{ timestamp: 'old', cpu_pct: 99 }] })
await flushPromises()
expect(fleet.nodeHistory.value).toEqual([])
expect(fleet.nodeHistoryLoading.value).toBe(true)
history.get('second')!({ history: [{ timestamp: 'current', cpu_pct: 10 }] })
await flushPromises()
expect(fleet.nodeHistory.value[0]?.timestamp).toBe('current')
expect(fleet.nodeHistoryLoading.value).toBe(false)
wrapper.unmount()
})
+8 -1
View File
@@ -273,6 +273,7 @@ export function useFleetData() {
const sortBy = ref<SortOption>(cached.sortBy ?? 'status') const sortBy = ref<SortOption>(cached.sortBy ?? 'status')
const chartWidth = ref(300) const chartWidth = ref(300)
let pollTimer: ReturnType<typeof setInterval> | null = null let pollTimer: ReturnType<typeof setInterval> | null = null
let historyRequest = 0
// --- Computed --- // --- Computed ---
@@ -384,17 +385,20 @@ export function useFleetData() {
} }
async function fetchNodeHistory(nodeId: string) { async function fetchNodeHistory(nodeId: string) {
const request = ++historyRequest
nodeHistoryLoading.value = true nodeHistoryLoading.value = true
try { try {
const data = await rpcClient.call<{ history?: NodeHistoryEntry[]; entries?: NodeHistoryEntry[] }>({ const data = await rpcClient.call<{ history?: NodeHistoryEntry[]; entries?: NodeHistoryEntry[] }>({
method: 'telemetry.fleet-node-history', method: 'telemetry.fleet-node-history',
params: { node_id: nodeId }, params: { node_id: nodeId },
}) })
if (request === historyRequest && selectedNodeId.value === nodeId) {
nodeHistory.value = normalizeNodeHistoryResponse(data) nodeHistory.value = normalizeNodeHistoryResponse(data)
}
} catch { } catch {
// Non-critical // Non-critical
} finally { } finally {
nodeHistoryLoading.value = false if (request === historyRequest) nodeHistoryLoading.value = false
} }
} }
@@ -477,6 +481,9 @@ export function useFleetData() {
// Fetch node history when selection changes // Fetch node history when selection changes
watch(selectedNodeId, (newId) => { watch(selectedNodeId, (newId) => {
historyRequest++
nodeHistory.value = []
nodeHistoryLoading.value = false
if (newId) { if (newId) {
fetchNodeHistory(newId) fetchNodeHistory(newId)
} else { } else {