dashboard pending-update count now matches the containers list
This commit is contained in:
3 files changed
+41
-2
No files matched your search
@@ -58,3 +58,25 @@ export function pendingRowsToClear(
|
||||
|
||||
return toClear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count pending rows that still map to a LIVE container (#1006). The dashboard tile
|
||||
* used to show the raw row count, but a row is keyed on containerId, so a container
|
||||
* recreated/removed OUT-OF-BAND (compose CLI, docker directly, Watchtower, image retag)
|
||||
* leaves an orphan row nothing prunes between checks. The containers page already
|
||||
* live-matches (a row shows only if its containerId exists), so the tile over-counted
|
||||
* and disagreed with the list. Counting only rows whose containerId is a currently
|
||||
* live container makes the tile agree with the list — no schema change, and it never
|
||||
* hides a real update (a live container with a pending row is still counted).
|
||||
*/
|
||||
export function countLivePending(
|
||||
pending: Array<{ containerId: string }>,
|
||||
liveContainerIds: Iterable<string>
|
||||
): number {
|
||||
const live = liveContainerIds instanceof Set ? liveContainerIds : new Set(liveContainerIds);
|
||||
let n = 0;
|
||||
for (const row of pending ?? []) {
|
||||
if (row?.containerId && live.has(row.containerId)) n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
getDiskUsage
|
||||
} from '$lib/server/docker';
|
||||
import { listComposeStacks } from '$lib/server/stacks';
|
||||
import { countLivePending } from '$lib/server/pending-updates-core';
|
||||
import { authorize } from '$lib/server/authorize';
|
||||
import { parseLabels } from '$lib/utils/label-colors';
|
||||
|
||||
@@ -281,7 +282,16 @@ export const GET: RequestHandler = async ({ cookies, url }) => {
|
||||
today: eventStats.today
|
||||
};
|
||||
|
||||
envStats.containers.pendingUpdates = pendingUpdates.length;
|
||||
// Count only pending rows that still map to a live container (#1006):
|
||||
// an out-of-band recreate/removal leaves orphan rows nothing prunes, and
|
||||
// the containers page already live-matches, so the raw count over-reported.
|
||||
// GUARD: only live-match when we actually HAVE the container list. If
|
||||
// listContainers timed out (`containers` is []) while there ARE pending
|
||||
// rows, the list is untrustworthy — fall back to the raw count rather than
|
||||
// hide real updates (over-count is annoying; under-count hides updates).
|
||||
envStats.containers.pendingUpdates = containers.length > 0
|
||||
? countLivePending(pendingUpdates, containers.map((c: any) => c.id))
|
||||
: pendingUpdates.length;
|
||||
|
||||
} catch (error) {
|
||||
// Convert technical error messages to user-friendly ones
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
DockerConnectionError
|
||||
} from '$lib/server/docker';
|
||||
import { listComposeStacks } from '$lib/server/stacks';
|
||||
import { countLivePending } from '$lib/server/pending-updates-core';
|
||||
import { authorize } from '$lib/server/authorize';
|
||||
import { prefersJSON, sseToJSON } from '$lib/server/sse';
|
||||
import type { EnvironmentStats } from '../+server';
|
||||
@@ -220,6 +221,8 @@ async function getEnvironmentStatsProgressive(
|
||||
today: eventStats.today
|
||||
};
|
||||
|
||||
// pendingUpdates is live-matched below once the container list is fetched (#1006);
|
||||
// seed to the raw count so a container-list timeout still shows something.
|
||||
envStats.containers.pendingUpdates = pendingUpdates.length;
|
||||
|
||||
if (recentEventsResult.events.length > 0) {
|
||||
@@ -309,7 +312,11 @@ async function getEnvironmentStatsProgressive(
|
||||
envStats.containers.paused = containers.filter((c: any) => c.state === 'paused').length;
|
||||
envStats.containers.restarting = containers.filter((c: any) => c.state === 'restarting').length;
|
||||
envStats.containers.unhealthy = containers.filter((c: any) => c.health === 'unhealthy').length;
|
||||
// Note: pendingUpdates is already set from DB query, preserve it
|
||||
// Refine the seeded raw count against the (now non-null) container list so
|
||||
// the tile agrees with the containers page (#1006). `containers` is
|
||||
// guaranteed real here (the null-guard above threw on a timeout), so no
|
||||
// empty-list fallback needed - unlike the non-stream twin.
|
||||
envStats.containers.pendingUpdates = countLivePending(pendingUpdates, containers.map((c: any) => c.id));
|
||||
envStats.loading!.containers = false;
|
||||
|
||||
onPartialUpdate({
|
||||
|
||||
Reference in new issue
Block a user