fix(database): improve web environment database connection handling
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 2m46s
Frontend CI / ota-android (push) Successful in 12m40s
Frontend CI / build-android-apk (push) Successful in 1h2m43s

- 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
This commit is contained in:
lafay
2026-04-04 02:38:56 +08:00
parent 69717ea407
commit 189b977fac

View File

@@ -53,6 +53,17 @@ async function withMutex<T>(fn: () => Promise<T>): Promise<T> {
async function openDatabaseWithRetry(dbName: string, maxRetries: number = 3): Promise<SQLite.SQLiteDatabase> {
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<void> => {
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<void> => {
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);
}