fix: Prevent agent type badge flapping in UnifiedAgents view

Track previously seen host types and preserve them when one data source
temporarily has no entry for a hostname. This prevents the "Host" or
"Docker" type badge from disappearing and reappearing when websocket
updates cause momentary state inconsistencies.

The fix only preserves types if the corresponding source array has any
data at all, ensuring that intentional host removal (both arrays empty
for that host) still works correctly.

Related to #773
This commit is contained in:
rcourtman 2025-12-02 11:29:03 +00:00
parent f4e3f625e7
commit 53a2c2a587

View file

@ -240,6 +240,10 @@ export const UnifiedAgents: Component = () => {
return `curl -fsSL ${pulseUrl()}/install.sh | sudo bash -s -- --uninstall`;
};
// Track previously seen host types to prevent flapping when one source temporarily has no data
// This preserves types we've seen before even if one array briefly becomes empty
let previousHostTypes = new Map<string, Set<'host' | 'docker'>>();
const allHosts = createMemo(() => {
const hosts = state.hosts || [];
const dockerHosts = state.dockerHosts || [];
@ -296,6 +300,33 @@ export const UnifiedAgents: Component = () => {
}
});
// Preserve previously seen types to prevent flapping
// If we previously saw both 'host' and 'docker' for a hostname, keep both
// unless BOTH sources are now empty (indicating intentional removal)
const newHostTypes = new Map<string, Set<'host' | 'docker'>>();
unified.forEach((entry, key) => {
const currentTypes = new Set(entry.types);
const prevTypes = previousHostTypes.get(key);
if (prevTypes && prevTypes.size > currentTypes.size) {
// We previously had more types - check if source data exists
// Only add back types if the corresponding source has ANY data
// (prevents permanent stickiness if a host is truly removed)
if (prevTypes.has('host') && !currentTypes.has('host') && hosts.length > 0) {
// Host type disappeared but we still have host data overall
// This is likely a transient state - preserve the host type
entry.types = Array.from(new Set([...entry.types, 'host']));
}
if (prevTypes.has('docker') && !currentTypes.has('docker') && dockerHosts.length > 0) {
// Docker type disappeared but we still have docker data overall
entry.types = Array.from(new Set([...entry.types, 'docker']));
}
}
newHostTypes.set(key, new Set(entry.types));
});
previousHostTypes = newHostTypes;
return Array.from(unified.values()).sort((a, b) => a.hostname.localeCompare(b.hostname));
});