perf(status): defer docker stats on startup
This commit is contained in:
parent
1c67468ba9
commit
69ae036f08
@ -345,9 +345,6 @@ class WebTerminal(MainTerminal):
|
|||||||
if self.terminal_manager:
|
if self.terminal_manager:
|
||||||
terminal_status = self.terminal_manager.list_terminals()
|
terminal_status = self.terminal_manager.list_terminals()
|
||||||
|
|
||||||
# 新增:对话状态
|
|
||||||
conversation_stats = self.context_manager.get_conversation_statistics()
|
|
||||||
|
|
||||||
# 构建状态信息
|
# 构建状态信息
|
||||||
limit_bytes = getattr(self, "project_storage_limit_bytes", None)
|
limit_bytes = getattr(self, "project_storage_limit_bytes", None)
|
||||||
status = {
|
status = {
|
||||||
@ -384,9 +381,11 @@ class WebTerminal(MainTerminal):
|
|||||||
# 新增:对话状态
|
# 新增:对话状态
|
||||||
"conversation": {
|
"conversation": {
|
||||||
"current_id": self.context_manager.current_conversation_id,
|
"current_id": self.context_manager.current_conversation_id,
|
||||||
"total_conversations": conversation_stats.get('total_conversations', 0),
|
# 首屏不再同步计算全量对话统计;统计面板按需调用
|
||||||
"total_messages": conversation_stats.get('total_messages', 0),
|
# /api/conversations/statistics,避免刷新时读取所有历史对话文件。
|
||||||
"total_tools": conversation_stats.get('total_tools', 0)
|
"total_conversations": 0,
|
||||||
|
"total_messages": 0,
|
||||||
|
"total_tools": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status["todo_list"] = self.context_manager.get_todo_snapshot()
|
status["todo_list"] = self.context_manager.get_todo_snapshot()
|
||||||
|
|||||||
@ -147,7 +147,9 @@ def get_status(terminal, workspace, username):
|
|||||||
status['project_path'] = str(workspace.project_path)
|
status['project_path'] = str(workspace.project_path)
|
||||||
phase_started_at = time.perf_counter()
|
phase_started_at = time.perf_counter()
|
||||||
try:
|
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:
|
except Exception as exc:
|
||||||
status['container'] = {"success": False, "error": str(exc)}
|
status['container'] = {"success": False, "error": str(exc)}
|
||||||
log_conn_diag(f"status container-status-failed user={username} error={exc}")
|
log_conn_diag(f"status container-status-failed user={username} error={exc}")
|
||||||
|
|||||||
@ -54,6 +54,8 @@ const buildDefaultQuota = (): UsageQuota => ({
|
|||||||
|
|
||||||
const PROJECT_STORAGE_POLL_INTERVAL_MS = 60_000;
|
const PROJECT_STORAGE_POLL_INTERVAL_MS = 60_000;
|
||||||
const PROJECT_STORAGE_POLL_INTERVAL_MAX_MS = 300_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', {
|
export const useResourceStore = defineStore('resource', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@ -79,7 +81,7 @@ export const useResourceStore = defineStore('resource', {
|
|||||||
lastContainerSample: null as ContainerSample | null,
|
lastContainerSample: null as ContainerSample | null,
|
||||||
containerStatsInFlight: false,
|
containerStatsInFlight: false,
|
||||||
containerStatsFailCount: 0,
|
containerStatsFailCount: 0,
|
||||||
containerStatsIntervalMs: 500,
|
containerStatsIntervalMs: CONTAINER_STATS_POLL_INTERVAL_MS,
|
||||||
containerStatsTimer: null as ReturnType<typeof setInterval> | null,
|
containerStatsTimer: null as ReturnType<typeof setInterval> | null,
|
||||||
projectStorageTimer: null as ReturnType<typeof setInterval> | null,
|
projectStorageTimer: null as ReturnType<typeof setInterval> | null,
|
||||||
projectStorageInFlight: false,
|
projectStorageInFlight: false,
|
||||||
@ -103,6 +105,11 @@ export const useResourceStore = defineStore('resource', {
|
|||||||
toggleTokenPanel() {
|
toggleTokenPanel() {
|
||||||
console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed);
|
console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed);
|
||||||
this.tokenPanelCollapsed = !this.tokenPanelCollapsed;
|
this.tokenPanelCollapsed = !this.tokenPanelCollapsed;
|
||||||
|
if (this.tokenPanelCollapsed) {
|
||||||
|
this.stopContainerStatsPolling();
|
||||||
|
} else {
|
||||||
|
this.startContainerStatsPolling();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async updateCurrentContextTokens(conversationId: string | null) {
|
async updateCurrentContextTokens(conversationId: string | null) {
|
||||||
if (!conversationId) {
|
if (!conversationId) {
|
||||||
@ -236,14 +243,17 @@ export const useResourceStore = defineStore('resource', {
|
|||||||
this.updateContainerStatus(data.data || null);
|
this.updateContainerStatus(data.data || null);
|
||||||
}
|
}
|
||||||
this.containerStatsFailCount = 0;
|
this.containerStatsFailCount = 0;
|
||||||
if (this.containerStatsIntervalMs > 500) {
|
if (this.containerStatsIntervalMs > CONTAINER_STATS_POLL_INTERVAL_MS) {
|
||||||
this._restartContainerStatsTimer(500);
|
this._restartContainerStatsTimer(CONTAINER_STATS_POLL_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('获取容器状态异常:', error);
|
console.warn('获取容器状态异常:', error);
|
||||||
this.containerStatsFailCount += 1;
|
this.containerStatsFailCount += 1;
|
||||||
if (this.containerStatsFailCount >= 3) {
|
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);
|
this._restartContainerStatsTimer(nextInterval);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -257,8 +267,11 @@ export const useResourceStore = defineStore('resource', {
|
|||||||
if (this.containerStatsTimer) {
|
if (this.containerStatsTimer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.tokenPanelCollapsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.containerStatsFailCount = 0;
|
this.containerStatsFailCount = 0;
|
||||||
this.containerStatsIntervalMs = 500;
|
this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
|
||||||
this.pollContainerStats();
|
this.pollContainerStats();
|
||||||
this.containerStatsTimer = setInterval(() => {
|
this.containerStatsTimer = setInterval(() => {
|
||||||
this.pollContainerStats();
|
this.pollContainerStats();
|
||||||
@ -290,7 +303,7 @@ export const useResourceStore = defineStore('resource', {
|
|||||||
this.stopContainerStatsPolling();
|
this.stopContainerStatsPolling();
|
||||||
} else {
|
} else {
|
||||||
this.containerStatsFailCount = 0;
|
this.containerStatsFailCount = 0;
|
||||||
this.containerStatsIntervalMs = 500;
|
this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
|
||||||
this.startContainerStatsPolling();
|
this.startContainerStatsPolling();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user