perf(web): optimize API polling frequency and respect page visibility

This commit is contained in:
duorameng
2026-06-30 11:59:58 +08:00
parent 837a53ecd3
commit c2eee38091
3 changed files with 69 additions and 4 deletions
+14 -1
View File
@@ -37,8 +37,9 @@ function handleNodeChange(val: any) {
function startPolling() {
stopPolling()
if (document.visibilityState === 'hidden') return
loadNodes()
timer = setInterval(loadNodes, 30000)
timer = setInterval(loadNodes, 120000) // 放宽至 2 分钟一次
}
function stopPolling() {
@@ -48,6 +49,16 @@ function stopPolling() {
}
}
function handleVisibilityChange() {
if (document.visibilityState === 'visible') {
if (isMaster.value) {
startPolling()
}
} else {
stopPolling()
}
}
async function checkRoleAndInit() {
try {
const role = await api.settings.get('interconnect', 'interconnect_role')
@@ -86,10 +97,12 @@ roleBus.on((newRole) => {
onMounted(async () => {
await checkRoleAndInit()
document.addEventListener('visibilitychange', handleVisibilityChange)
})
onUnmounted(() => {
stopPolling()
document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>
+19 -1
View File
@@ -9,6 +9,9 @@ import { api, type AppLog, LOG_CATEGORY, LOG_STATUS } from '@/api'
import { toast } from 'vue-sonner'
import { format } from 'date-fns'
import { eventBus } from '@/utils/event-bus'
import { LOG_EVENTS } from '@/constants'
const notices = ref<AppLog[]>([])
const unreadCount = ref(0)
const loading = ref(false)
@@ -56,12 +59,27 @@ async function markAllAsRead() {
}
let timer: number
let unsubscribe: () => void
onMounted(() => {
fetchNotices()
timer = window.setInterval(fetchNotices, 60000) // 每分钟拉取一次
// 订阅 WebSocket 实时事件,在收到新系统日志通知时主动刷新
unsubscribe = eventBus.subscribe((msg) => {
if (msg.type === LOG_EVENTS.ADDED) {
const log = msg.payload
if (log && log.category === LOG_CATEGORY.SYSTEM_NOTICE) {
fetchNotices()
}
}
})
// 10 分钟一次的长轮询作为断连兜底
timer = window.setInterval(fetchNotices, 10 * 60 * 1000)
})
onUnmounted(() => {
if (unsubscribe) unsubscribe()
if (timer) clearInterval(timer)
})
+36 -2
View File
@@ -64,6 +64,16 @@ async function loadAgents() {
}
}
async function refreshAgentsOnly() {
if (document.visibilityState === 'hidden') return
try {
const agentList = await api.agents.list()
agents.value = agentList
} catch (e) {
console.error('Failed to poll agent status', e)
}
}
// Handler functions for Agent
function viewDetail(agent: Agent) {
agentDetailDialogRef.value?.openDialog(agent)
@@ -103,13 +113,37 @@ function openEditToken(token: AgentToken) {
editTokenDialogRef.value?.openEdit(token)
}
function startPolling() {
stopPolling()
if (document.visibilityState === 'hidden') return
refreshTimer = setInterval(refreshAgentsOnly, 30000) // 仅轮询 Agent 在线状态,频率放宽至 30s
}
function stopPolling() {
if (refreshTimer) {
clearInterval(refreshTimer)
refreshTimer = null
}
}
function handleVisibilityChange() {
if (document.visibilityState === 'visible') {
refreshAgentsOnly()
startPolling()
} else {
stopPolling()
}
}
onMounted(() => {
loadAgents()
refreshTimer = setInterval(loadAgents, 10000)
startPolling()
document.addEventListener('visibilitychange', handleVisibilityChange)
})
onUnmounted(() => {
if (refreshTimer) clearInterval(refreshTimer)
stopPolling()
document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>