This commit is contained in:
jarek committed 2026-01-22 16:23:26 +01:00
1 parent a3cc26d958
commit 86a06d9de0
32 files changed
+799 -522

No files matched your search

+5 -1
View File
@@ -20,6 +20,9 @@ import { listComposeStacks } from '$lib/server/stacks';
import { authorize } from '$lib/server/authorize';
import { parseLabels } from '$lib/utils/label-colors';
// Skip disk usage collection (Synology NAS performance fix)
const SKIP_DF_COLLECTION = process.env.SKIP_DF_COLLECTION === 'true' || process.env.SKIP_DF_COLLECTION === '1';
// Helper to add timeout to promises
function withTimeout<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T> {
return Promise.race([
@@ -200,13 +203,14 @@ export const GET: RequestHandler = async ({ cookies, url }) => {
envStats.online = true;
// Fetch all data in parallel (with 10 second timeout per operation)
// Disk usage can be disabled with SKIP_DF_COLLECTION for Synology NAS devices
const [containers, images, volumes, networks, stacks, diskUsage] = await Promise.all([
withTimeout(listContainers(true, env.id).catch(() => []), 10000, []),
withTimeout(listImages(env.id).catch(() => []), 10000, []),
withTimeout(listVolumes(env.id).catch(() => []), 10000, []),
withTimeout(listNetworks(env.id).catch(() => []), 10000, []),
withTimeout(listComposeStacks(env.id).catch(() => []), 10000, []),
withTimeout(getDiskUsage(env.id).catch(() => null), 10000, null)
SKIP_DF_COLLECTION ? Promise.resolve(null) : withTimeout(getDiskUsage(env.id).catch(() => null), 10000, null)
]);
// Process containers
@@ -21,6 +21,9 @@ import { authorize } from '$lib/server/authorize';
import type { EnvironmentStats } from '../+server';
import { parseLabels } from '$lib/utils/label-colors';
// Skip disk usage collection (Synology NAS performance fix)
const SKIP_DF_COLLECTION = process.env.SKIP_DF_COLLECTION === 'true' || process.env.SKIP_DF_COLLECTION === '1';
// Helper to add timeout to promises
function withTimeout<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T> {
return Promise.race([
@@ -31,6 +34,7 @@ function withTimeout<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T
// Disk usage cache - getDiskUsage() is very slow (30s timeout) but data changes rarely
// Cache per environment with 5-minute TTL
// DISABLED when SKIP_DF_COLLECTION is set (kills Synology NAS devices)
interface DiskUsageCache {
data: any;
timestamp: number;
@@ -344,37 +348,49 @@ async function getEnvironmentStatsProgressive(
});
// PHASE 3: Disk usage (slow - includes volumes) - uses cache for better performance
const diskUsagePromise = getCachedDiskUsage(env.id)
.then((diskUsage) => {
if (diskUsage) {
// Update images with disk usage data (more accurate)
envStats.images.total = diskUsage.Images?.length || envStats.images.total;
envStats.images.totalSize = diskUsage.Images?.reduce((sum: number, img: any) => sum + getValidSize(img.Size), 0) || envStats.images.totalSize;
// Volumes from disk usage
envStats.volumes.total = diskUsage.Volumes?.length || 0;
envStats.volumes.totalSize = diskUsage.Volumes?.reduce((sum: number, vol: any) => sum + getValidSize(vol.UsageData?.Size), 0) || 0;
// Containers disk size
envStats.containersSize = diskUsage.Containers?.reduce((sum: number, c: any) => sum + getValidSize(c.SizeRw), 0) || 0;
// Build cache
envStats.buildCacheSize = diskUsage.BuildCache?.reduce((sum: number, bc: any) => sum + getValidSize(bc.Size), 0) || 0;
}
// Can be disabled with SKIP_DF_COLLECTION env var for Synology NAS
const diskUsagePromise = SKIP_DF_COLLECTION
? Promise.resolve(null).then(() => {
envStats.loading!.volumes = false;
envStats.loading!.diskUsage = false;
onPartialUpdate({
id: env.id,
images: { ...envStats.images },
volumes: { ...envStats.volumes },
containersSize: envStats.containersSize,
buildCacheSize: envStats.buildCacheSize,
loading: { ...envStats.loading! }
});
return null;
})
: getCachedDiskUsage(env.id)
.then((diskUsage) => {
if (diskUsage) {
// Update images with disk usage data (more accurate)
envStats.images.total = diskUsage.Images?.length || envStats.images.total;
envStats.images.totalSize = diskUsage.Images?.reduce((sum: number, img: any) => sum + getValidSize(img.Size), 0) || envStats.images.totalSize;
return diskUsage;
});
// Volumes from disk usage
envStats.volumes.total = diskUsage.Volumes?.length || 0;
envStats.volumes.totalSize = diskUsage.Volumes?.reduce((sum: number, vol: any) => sum + getValidSize(vol.UsageData?.Size), 0) || 0;
// Containers disk size
envStats.containersSize = diskUsage.Containers?.reduce((sum: number, c: any) => sum + getValidSize(c.SizeRw), 0) || 0;
// Build cache
envStats.buildCacheSize = diskUsage.BuildCache?.reduce((sum: number, bc: any) => sum + getValidSize(bc.Size), 0) || 0;
}
envStats.loading!.volumes = false;
envStats.loading!.diskUsage = false;
onPartialUpdate({
id: env.id,
images: { ...envStats.images },
volumes: { ...envStats.volumes },
containersSize: envStats.containersSize,
buildCacheSize: envStats.buildCacheSize,
loading: { ...envStats.loading! }
});
return diskUsage;
});
// PHASE 4: Top containers (slow - requires per-container stats)
// Limited to TOP_CONTAINERS_LIMIT containers to reduce API calls