From 4cc822c4f6749cd55815dd83fcb054a495ead7fb Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 3 Feb 2026 14:44:39 +0800 Subject: [PATCH] fix: Resolve SQLITE_BUSY by enabling WAL and fixing isolate init --- lib/src/storage/isolate_event_storage.dart | 22 +++++++++++++++++----- lib/src/storage/sqflite_event_storage.dart | 17 ++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/src/storage/isolate_event_storage.dart b/lib/src/storage/isolate_event_storage.dart index 8cf214a..4080ab8 100644 --- a/lib/src/storage/isolate_event_storage.dart +++ b/lib/src/storage/isolate_event_storage.dart @@ -256,16 +256,28 @@ Future _storageWorkerEntry(_WorkerInit init) async { } final commandPort = ReceivePort(); - init.responsePort.send({ - 'type': _msgReady, - 'sendPort': commandPort.sendPort, - }); final storage = switch (init.backend) { IsolateStorageBackend.sqlite => SqfliteEventStorage(), IsolateStorageBackend.memory => _MemoryEventStorage(), }; - await storage.init(); + + try { + await storage.init(); + } on Object catch (e, st) { + Logger.error('Isolate 存储初始化失败', e, st); + // 初始化失败时,不发送 ready 信号,或发送错误信号(当前协议简单,暂不发送 ready 即视为失败/超时)。 + // 但为了让主 isolate 能够尽快失败而不是超时,我们可以考虑扩展协议,但目前最稳妥的是让主 isolate 超时抛错。 + // 这里简单地关闭端口退出。 + commandPort.close(); + return; + } + + // 初始化成功后再发送 ready 信号。 + init.responsePort.send({ + 'type': _msgReady, + 'sendPort': commandPort.sendPort, + }); await for (final message in commandPort) { if (message is! Map) { diff --git a/lib/src/storage/sqflite_event_storage.dart b/lib/src/storage/sqflite_event_storage.dart index 18eb1b6..963ac92 100644 --- a/lib/src/storage/sqflite_event_storage.dart +++ b/lib/src/storage/sqflite_event_storage.dart @@ -36,9 +36,8 @@ class SqfliteEventStorage implements EventStorage { return; } - final directory = - await (_documentsDirectoryProvider?.call() ?? - getApplicationDocumentsDirectory()); + final directory = await (_documentsDirectoryProvider?.call() ?? + getApplicationDocumentsDirectory()); final dbPath = p.join(directory.path, DbConstants.dbName); final factory = _databaseFactory ?? databaseFactory; @@ -56,6 +55,15 @@ class SqfliteEventStorage implements EventStorage { } }, // coverage:ignore-end + onConfigure: (Database db) async { + // 启用 WAL 模式以支持更高并发读写,减少 SQLITE_BUSY。 + // 注意:PRAGMA journal_mode 会返回结果,使用 execute 在 Android 上可能会报错,需改用 rawQuery。 + await db.rawQuery('PRAGMA journal_mode = WAL;'); + }, + onOpen: (Database db) async { + // 确保表存在(针对多个 Store 共享同一 DB 文件且部分表可能未创建的情况)。 + await _createTables(db); + }, ), ); @@ -72,8 +80,7 @@ class SqfliteEventStorage implements EventStorage { ); '''); - const createIndexSql = - 'CREATE INDEX IF NOT EXISTS idx_events_create_time ' + const createIndexSql = 'CREATE INDEX IF NOT EXISTS idx_events_create_time ' 'ON $_tableEvents(create_time);'; await db.execute(createIndexSql); }