perf(status): defer docker stats on startup

This commit is contained in:
JOJO 2026-05-29 13:55:54 +08:00
parent 1c67468ba9
commit 69ae036f08
3 changed files with 27 additions and 13 deletions

View File

@ -345,9 +345,6 @@ class WebTerminal(MainTerminal):
if self.terminal_manager:
terminal_status = self.terminal_manager.list_terminals()
# 新增:对话状态
conversation_stats = self.context_manager.get_conversation_statistics()
# 构建状态信息
limit_bytes = getattr(self, "project_storage_limit_bytes", None)
status = {
@ -384,9 +381,11 @@ class WebTerminal(MainTerminal):
# 新增:对话状态
"conversation": {
"current_id": self.context_manager.current_conversation_id,
"total_conversations": conversation_stats.get('total_conversations', 0),
"total_messages": conversation_stats.get('total_messages', 0),
"total_tools": conversation_stats.get('total_tools', 0)
# 首屏不再同步计算全量对话统计;统计面板按需调用
# /api/conversations/statistics避免刷新时读取所有历史对话文件。
"total_conversations": 0,
"total_messages": 0,
"total_tools": 0
}
}
status["todo_list"] = self.context_manager.get_todo_snapshot()

View File

@ -147,7 +147,9 @@ def get_status(terminal, workspace, username):
status['project_path'] = str(workspace.project_path)
phase_started_at = time.perf_counter()
try:
status['container'] = container_manager.get_container_status(username)
# 首屏状态只需要容器是否存在/运行等轻量信息Docker stats 很慢,
# 由 /api/container-status 在用量面板需要时单独拉取。
status['container'] = container_manager.get_container_status(username, include_stats=False)
except Exception as exc:
status['container'] = {"success": False, "error": str(exc)}
log_conn_diag(f"status container-status-failed user={username} error={exc}")

View File

@ -54,6 +54,8 @@ const buildDefaultQuota = (): UsageQuota => ({
const PROJECT_STORAGE_POLL_INTERVAL_MS = 60_000;
const PROJECT_STORAGE_POLL_INTERVAL_MAX_MS = 300_000;
const CONTAINER_STATS_POLL_INTERVAL_MS = 5_000;
const CONTAINER_STATS_POLL_INTERVAL_MAX_MS = 30_000;
export const useResourceStore = defineStore('resource', {
state: () => ({
@ -79,7 +81,7 @@ export const useResourceStore = defineStore('resource', {
lastContainerSample: null as ContainerSample | null,
containerStatsInFlight: false,
containerStatsFailCount: 0,
containerStatsIntervalMs: 500,
containerStatsIntervalMs: CONTAINER_STATS_POLL_INTERVAL_MS,
containerStatsTimer: null as ReturnType<typeof setInterval> | null,
projectStorageTimer: null as ReturnType<typeof setInterval> | null,
projectStorageInFlight: false,
@ -103,6 +105,11 @@ export const useResourceStore = defineStore('resource', {
toggleTokenPanel() {
console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed);
this.tokenPanelCollapsed = !this.tokenPanelCollapsed;
if (this.tokenPanelCollapsed) {
this.stopContainerStatsPolling();
} else {
this.startContainerStatsPolling();
}
},
async updateCurrentContextTokens(conversationId: string | null) {
if (!conversationId) {
@ -236,14 +243,17 @@ export const useResourceStore = defineStore('resource', {
this.updateContainerStatus(data.data || null);
}
this.containerStatsFailCount = 0;
if (this.containerStatsIntervalMs > 500) {
this._restartContainerStatsTimer(500);
if (this.containerStatsIntervalMs > CONTAINER_STATS_POLL_INTERVAL_MS) {
this._restartContainerStatsTimer(CONTAINER_STATS_POLL_INTERVAL_MS);
}
} catch (error) {
console.warn('获取容器状态异常:', error);
this.containerStatsFailCount += 1;
if (this.containerStatsFailCount >= 3) {
const nextInterval = Math.min(this.containerStatsIntervalMs * 2, 10_000);
const nextInterval = Math.min(
this.containerStatsIntervalMs * 2,
CONTAINER_STATS_POLL_INTERVAL_MAX_MS
);
this._restartContainerStatsTimer(nextInterval);
}
} finally {
@ -257,8 +267,11 @@ export const useResourceStore = defineStore('resource', {
if (this.containerStatsTimer) {
return;
}
if (this.tokenPanelCollapsed) {
return;
}
this.containerStatsFailCount = 0;
this.containerStatsIntervalMs = 500;
this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
this.pollContainerStats();
this.containerStatsTimer = setInterval(() => {
this.pollContainerStats();
@ -290,7 +303,7 @@ export const useResourceStore = defineStore('resource', {
this.stopContainerStatsPolling();
} else {
this.containerStatsFailCount = 0;
this.containerStatsIntervalMs = 500;
this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
this.startContainerStatsPolling();
}
};