fix: apply empty agent updates immediately when existing agents are stale

The anti-flapping logic previously required 3 consecutive empty updates
before clearing stale agents from the UI. Now if all existing hosts/dockerHosts
have lastSeen > 60 seconds ago, empty updates are applied immediately.

This fixes the issue where removed agents stayed visible for too long.
This commit is contained in:
rcourtman 2025-12-13 22:41:15 +00:00
parent b02a1556b7
commit 68456763f9

View file

@ -443,14 +443,25 @@ export function createWebSocketStore(url: string) {
if (incomingHosts.length === 0) { if (incomingHosts.length === 0) {
consecutiveEmptyDockerUpdates += 1; consecutiveEmptyDockerUpdates += 1;
// Check if all existing docker hosts are stale (>60s since lastSeen)
// If so, they're probably really gone - apply the empty update immediately
const now = Date.now();
const staleThresholdMs = 60_000; // 60 seconds
const existingDockerHosts = state.dockerHosts || [];
const allStale = existingDockerHosts.length === 0 || existingDockerHosts.every(
(h) => !h.lastSeen || (now - h.lastSeen) > staleThresholdMs
);
shouldApplyDockerHosts = shouldApplyDockerHosts =
!hasReceivedNonEmptyDockerHosts || !hasReceivedNonEmptyDockerHosts ||
allStale ||
consecutiveEmptyDockerUpdates >= 3 || consecutiveEmptyDockerUpdates >= 3 ||
message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE; message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE;
if (shouldApplyDockerHosts) { if (shouldApplyDockerHosts) {
logger.debug('[WebSocket] Updating dockerHosts', { logger.debug('[WebSocket] Updating dockerHosts', {
count: incomingHosts.length, count: incomingHosts.length,
reason: allStale ? 'allStale' : 'threshold',
}); });
processedDockerHosts = mergeDockerHostRevocations(incomingHosts); processedDockerHosts = mergeDockerHostRevocations(incomingHosts);
} else { } else {
@ -486,14 +497,25 @@ export function createWebSocketStore(url: string) {
if (incomingHosts.length === 0) { if (incomingHosts.length === 0) {
consecutiveEmptyHostUpdates += 1; consecutiveEmptyHostUpdates += 1;
// Check if all existing hosts are stale (>60s since lastSeen)
// If so, they're probably really gone - apply the empty update immediately
const now = Date.now();
const staleThresholdMs = 60_000; // 60 seconds
const existingHosts = state.hosts || [];
const allHostsStale = existingHosts.length === 0 || existingHosts.every(
(h) => !h.lastSeen || (now - h.lastSeen) > staleThresholdMs
);
shouldApplyHosts = shouldApplyHosts =
!hasReceivedNonEmptyHosts || !hasReceivedNonEmptyHosts ||
allHostsStale ||
consecutiveEmptyHostUpdates >= 3 || consecutiveEmptyHostUpdates >= 3 ||
message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE; message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE;
if (shouldApplyHosts) { if (shouldApplyHosts) {
logger.debug('[WebSocket] Updating hosts', { logger.debug('[WebSocket] Updating hosts', {
count: incomingHosts.length, count: incomingHosts.length,
reason: allHostsStale ? 'allStale' : 'threshold',
}); });
processedHosts = mergeHostRevocations(incomingHosts); processedHosts = mergeHostRevocations(incomingHosts);
} else { } else {