diff --git a/static/src/stores/resource.ts b/static/src/stores/resource.ts index 94d3786..fec38ca 100644 --- a/static/src/stores/resource.ts +++ b/static/src/stores/resource.ts @@ -76,6 +76,9 @@ export const useResourceStore = defineStore('resource', { up_bps: null } as ContainerNetRate, lastContainerSample: null as ContainerSample | null, + containerStatsInFlight: false, + containerStatsFailCount: 0, + containerStatsIntervalMs: 500, containerStatsTimer: null as ReturnType | null, projectStorageTimer: null as ReturnType | null, projectStorageInFlight: false, @@ -202,33 +205,71 @@ export const useResourceStore = defineStore('resource', { this.containerStatus = status; }, async pollContainerStats() { + if (typeof document !== 'undefined' && document.hidden) { + return; + } + if (this.containerStatsInFlight) { + return; + } + this.containerStatsInFlight = true; + const controller = typeof AbortController !== 'undefined' ? new AbortController() : null; + const timeoutId = controller ? window.setTimeout(() => controller.abort(), 4000) : null; try { - const response = await fetch('/api/container-status'); + const response = await fetch('/api/container-status', { + signal: controller?.signal + }); if (!response.ok) { - return; + throw new Error(`http-${response.status}`); } const data = await response.json(); if (data.success) { this.updateContainerStatus(data.data || null); } + this.containerStatsFailCount = 0; + if (this.containerStatsIntervalMs > 500) { + this._restartContainerStatsTimer(500); + } } catch (error) { console.warn('获取容器状态异常:', error); + this.containerStatsFailCount += 1; + if (this.containerStatsFailCount >= 3) { + const nextInterval = Math.min(this.containerStatsIntervalMs * 2, 10_000); + this._restartContainerStatsTimer(nextInterval); + } + } finally { + this.containerStatsInFlight = false; + if (timeoutId) { + clearTimeout(timeoutId); + } } }, startContainerStatsPolling() { if (this.containerStatsTimer) { return; } + this.containerStatsFailCount = 0; + this.containerStatsIntervalMs = 500; this.pollContainerStats(); this.containerStatsTimer = setInterval(() => { this.pollContainerStats(); - }, 500); + }, this.containerStatsIntervalMs); }, stopContainerStatsPolling() { if (this.containerStatsTimer) { clearInterval(this.containerStatsTimer); this.containerStatsTimer = null; } + this.containerStatsInFlight = false; + }, + _restartContainerStatsTimer(interval: number) { + if (this.containerStatsTimer) { + clearInterval(this.containerStatsTimer); + this.containerStatsTimer = null; + } + this.containerStatsIntervalMs = interval; + this.containerStatsTimer = setInterval(() => { + this.pollContainerStats(); + }, this.containerStatsIntervalMs); }, async pollProjectStorage() { if (this.projectStorageInFlight) {