mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
perf(export): prioritize active tab counts and avoid full-list warmup
This commit is contained in:
@@ -198,6 +198,7 @@ class ChatService {
|
|||||||
private sessionTablesCache = new Map<string, Array<{ tableName: string; dbPath: string }>>()
|
private sessionTablesCache = new Map<string, Array<{ tableName: string; dbPath: string }>>()
|
||||||
private readonly sessionTablesCacheTtl = 300000 // 5分钟
|
private readonly sessionTablesCacheTtl = 300000 // 5分钟
|
||||||
private sessionMessageCountCache = new Map<string, { count: number; updatedAt: number }>()
|
private sessionMessageCountCache = new Map<string, { count: number; updatedAt: number }>()
|
||||||
|
private sessionMessageCountHintCache = new Map<string, number>()
|
||||||
private sessionMessageCountCacheScope = ''
|
private sessionMessageCountCacheScope = ''
|
||||||
private readonly sessionMessageCountCacheTtlMs = 10 * 60 * 1000
|
private readonly sessionMessageCountCacheTtlMs = 10 * 60 * 1000
|
||||||
|
|
||||||
@@ -369,6 +370,7 @@ class ChatService {
|
|||||||
if (!connectResult.success) {
|
if (!connectResult.success) {
|
||||||
return { success: false, error: connectResult.error }
|
return { success: false, error: connectResult.error }
|
||||||
}
|
}
|
||||||
|
this.refreshSessionMessageCountCacheScope()
|
||||||
|
|
||||||
const result = await wcdbService.getSessions()
|
const result = await wcdbService.getSessions()
|
||||||
if (!result.success || !result.sessions) {
|
if (!result.success || !result.sessions) {
|
||||||
@@ -462,6 +464,14 @@ class ChatService {
|
|||||||
lastSenderDisplayName: row.last_sender_display_name,
|
lastSenderDisplayName: row.last_sender_display_name,
|
||||||
selfWxid: myWxid
|
selfWxid: myWxid
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (typeof messageCountHint === 'number') {
|
||||||
|
this.sessionMessageCountHintCache.set(username, messageCountHint)
|
||||||
|
this.sessionMessageCountCache.set(username, {
|
||||||
|
count: messageCountHint,
|
||||||
|
updatedAt: Date.now()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量拉取 extra_buffer 状态(isFolded/isMuted),不阻塞主流程
|
// 批量拉取 extra_buffer 状态(isFolded/isMuted),不阻塞主流程
|
||||||
@@ -824,6 +834,16 @@ class ChatService {
|
|||||||
const cached = this.sessionMessageCountCache.get(sessionId)
|
const cached = this.sessionMessageCountCache.get(sessionId)
|
||||||
if (cached && now - cached.updatedAt <= this.sessionMessageCountCacheTtlMs) {
|
if (cached && now - cached.updatedAt <= this.sessionMessageCountCacheTtlMs) {
|
||||||
counts[sessionId] = cached.count
|
counts[sessionId] = cached.count
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const hintCount = this.sessionMessageCountHintCache.get(sessionId)
|
||||||
|
if (typeof hintCount === 'number' && Number.isFinite(hintCount) && hintCount >= 0) {
|
||||||
|
counts[sessionId] = Math.floor(hintCount)
|
||||||
|
this.sessionMessageCountCache.set(sessionId, {
|
||||||
|
count: Math.floor(hintCount),
|
||||||
|
updatedAt: now
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
pendingSessionIds.push(sessionId)
|
pendingSessionIds.push(sessionId)
|
||||||
}
|
}
|
||||||
@@ -1511,6 +1531,7 @@ class ChatService {
|
|||||||
if (scope === this.sessionMessageCountCacheScope) return
|
if (scope === this.sessionMessageCountCacheScope) return
|
||||||
this.sessionMessageCountCacheScope = scope
|
this.sessionMessageCountCacheScope = scope
|
||||||
this.sessionMessageCountCache.clear()
|
this.sessionMessageCountCache.clear()
|
||||||
|
this.sessionMessageCountHintCache.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async collectSessionExportStats(
|
private async collectSessionExportStats(
|
||||||
|
|||||||
@@ -237,9 +237,8 @@ const timestampOrDash = (timestamp?: number): string => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createTaskId = (): string => `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
const createTaskId = (): string => `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
||||||
const MESSAGE_COUNT_VIEWPORT_PREFETCH = 120
|
const MESSAGE_COUNT_VIEWPORT_PREFETCH = 180
|
||||||
const MESSAGE_COUNT_BACKGROUND_BATCH = 90
|
const MESSAGE_COUNT_ACTIVE_TAB_WARMUP_LIMIT = 960
|
||||||
const MESSAGE_COUNT_BACKGROUND_INTERVAL_MS = 90
|
|
||||||
const METRICS_VIEWPORT_PREFETCH = 90
|
const METRICS_VIEWPORT_PREFETCH = 90
|
||||||
const METRICS_BACKGROUND_BATCH = 40
|
const METRICS_BACKGROUND_BATCH = 40
|
||||||
const METRICS_BACKGROUND_INTERVAL_MS = 220
|
const METRICS_BACKGROUND_INTERVAL_MS = 220
|
||||||
@@ -773,7 +772,7 @@ function ExportPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const batchSize = pending.length > 100 ? 48 : 28
|
const batchSize = pending.length > 260 ? 260 : pending.length
|
||||||
for (let i = 0; i < pending.length; i += batchSize) {
|
for (let i = 0; i < pending.length; i += batchSize) {
|
||||||
if (loadTokenAtStart !== sessionLoadTokenRef.current) return
|
if (loadTokenAtStart !== sessionLoadTokenRef.current) return
|
||||||
const chunk = pending.slice(i, i + batchSize)
|
const chunk = pending.slice(i, i + batchSize)
|
||||||
@@ -872,6 +871,16 @@ function ExportPage() {
|
|||||||
void ensureSessionMessageCounts(targets)
|
void ensureSessionMessageCounts(targets)
|
||||||
}, [visibleSessions, ensureSessionMessageCounts])
|
}, [visibleSessions, ensureSessionMessageCounts])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (sessions.length === 0) return
|
||||||
|
const activeTabTargets = sessions
|
||||||
|
.filter(session => session.kind === activeTab)
|
||||||
|
.sort((a, b) => (b.sortTimestamp || b.lastTimestamp || 0) - (a.sortTimestamp || a.lastTimestamp || 0))
|
||||||
|
.slice(0, MESSAGE_COUNT_ACTIVE_TAB_WARMUP_LIMIT)
|
||||||
|
if (activeTabTargets.length === 0) return
|
||||||
|
void ensureSessionMessageCounts(activeTabTargets)
|
||||||
|
}, [sessions, activeTab, ensureSessionMessageCounts])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const targets = visibleSessions.slice(0, METRICS_VIEWPORT_PREFETCH)
|
const targets = visibleSessions.slice(0, METRICS_VIEWPORT_PREFETCH)
|
||||||
void ensureSessionMetrics(targets)
|
void ensureSessionMetrics(targets)
|
||||||
@@ -889,26 +898,6 @@ function ExportPage() {
|
|||||||
void ensureSessionMetrics(rangeSessions)
|
void ensureSessionMetrics(rangeSessions)
|
||||||
}, [ensureSessionMessageCounts, ensureSessionMetrics])
|
}, [ensureSessionMessageCounts, ensureSessionMetrics])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (sessions.length === 0) return
|
|
||||||
const prioritySessions = [
|
|
||||||
...sessions.filter(session => session.kind === activeTab),
|
|
||||||
...sessions.filter(session => session.kind !== activeTab)
|
|
||||||
]
|
|
||||||
let cursor = 0
|
|
||||||
const timer = window.setInterval(() => {
|
|
||||||
if (cursor >= prioritySessions.length) {
|
|
||||||
window.clearInterval(timer)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const chunk = prioritySessions.slice(cursor, cursor + MESSAGE_COUNT_BACKGROUND_BATCH)
|
|
||||||
cursor += MESSAGE_COUNT_BACKGROUND_BATCH
|
|
||||||
void ensureSessionMessageCounts(chunk)
|
|
||||||
}, MESSAGE_COUNT_BACKGROUND_INTERVAL_MS)
|
|
||||||
|
|
||||||
return () => window.clearInterval(timer)
|
|
||||||
}, [sessions, activeTab, ensureSessionMessageCounts])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sessions.length === 0) return
|
if (sessions.length === 0) return
|
||||||
const prioritySessions = [
|
const prioritySessions = [
|
||||||
|
|||||||
Reference in New Issue
Block a user