From 189b977faca73f049a919f47fb951c6e0d642d55 Mon Sep 17 00:00:00 2001 From: lafay <2021211506@stu.hit.edu.cn> Date: Sat, 4 Apr 2026 02:38:56 +0800 Subject: [PATCH] fix(database): improve web environment database connection handling - Add pre-open check for web to release potentially stale OPFS handles - Unify close logic across platforms instead of skipping for web - Add proper logging for connection lifecycle operations - Remove obsolete error check for "cannot create file" during retries --- src/services/database.ts | 48 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/services/database.ts b/src/services/database.ts index b8337e7..07cb59d 100644 --- a/src/services/database.ts +++ b/src/services/database.ts @@ -53,6 +53,17 @@ async function withMutex(fn: () => Promise): Promise { async function openDatabaseWithRetry(dbName: string, maxRetries: number = 3): Promise { const isWeb = typeof window !== 'undefined'; + if (isWeb) { + try { + const tempDb = await SQLite.openDatabaseAsync(dbName); + await tempDb.closeAsync(); + console.log('[Database] Web: 预打开成功,已释放可能残留的句柄'); + } catch (e) { + console.warn('[Database] Web: 预打开失败:', String(e)); + } + await new Promise(r => setTimeout(r, 50)); + } + for (let attempt = 0; attempt <= maxRetries; attempt++) { try { const database = await SQLite.openDatabaseAsync(dbName); @@ -66,7 +77,7 @@ async function openDatabaseWithRetry(dbName: string, maxRetries: number = 3): Pr console.warn(`[Database] ${delay}ms 后重试...`); await new Promise(r => setTimeout(r, delay)); - if (msg.includes('Invalid VFS state') || msg.includes('cannot create file')) { + if (msg.includes('Invalid VFS state')) { try { await SQLite.deleteDatabaseAsync(dbName); console.warn('[Database] 已删除损坏的数据库文件'); @@ -237,20 +248,19 @@ export const initDatabase = async (userId?: string): Promise => { const isWeb = typeof window !== 'undefined'; if (db) { + console.log(`[Database ${mutexId}] 关闭旧数据库连接...`); + try { + await db.closeAsync(); + console.log(`[Database ${mutexId}] 旧连接已关闭`); + } catch (e) { + console.warn(`[Database ${mutexId}] 关闭旧连接失败:`, e); + } + db = null; + currentDbUserId = null; + isInitialized = false; + if (isWeb) { - console.log(`[Database ${mutexId}] Web:切换用户,直接置空旧连接`); - db = null; - currentDbUserId = null; - isInitialized = false; - } else { - try { - await db.closeAsync(); - } catch (e) { - console.warn(`[Database ${mutexId}] 关闭旧连接失败:`, e); - } - db = null; - currentDbUserId = null; - isInitialized = false; + await new Promise(r => setTimeout(r, 100)); } } @@ -285,17 +295,9 @@ export const closeDatabase = async (): Promise => { await withMutex(async () => { if (!db) return; - const isWeb = typeof window !== 'undefined'; - if (isWeb) { - console.log('[Database] Web 环境:跳过关闭数据库,避免 OPFS 句柄冲突'); - db = null; - currentDbUserId = null; - isInitialized = false; - return; - } - try { await db.closeAsync(); + console.log('[Database] 数据库已关闭'); } catch (e) { console.warn('[Database] 关闭失败:', e); }