From daabd546493d98aa4bf1aec5515b25ae152237c6 Mon Sep 17 00:00:00 2001 From: xiaowei Date: Sat, 30 May 2026 17:35:29 +0800 Subject: [PATCH] fix(graph_sqlite): add busy_timeout + stale WAL/SHM cleanup on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: No busy_timeout set → immediate 'database is locked' on restart when stale WAL/SHM/journal files remain from crashed previous instance. Fix: - On open(): clean stale -wal/-shm/-journal files (only if main db exists) - After sqlite3_open(): set busy_timeout=10000ms (10s wait for locks) - This eliminates the InMemoryGraph fallback on restart --- go/internal/governance/graph_sqlite.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/go/internal/governance/graph_sqlite.go b/go/internal/governance/graph_sqlite.go index 8e9b0f8..8f408c2 100644 --- a/go/internal/governance/graph_sqlite.go +++ b/go/internal/governance/graph_sqlite.go @@ -7,12 +7,16 @@ package governance #cgo LDFLAGS: -lsqlite3 #include #include + +// busy_timeout 是 Go/C 混合文件中直接使用 C 函数 +// sqlite3_busy_timeout 在 sqlite3.h 中声明 */ import "C" import ( "encoding/json" "fmt" + "os" "strings" "sync" "unicode" @@ -32,6 +36,18 @@ func NewSQLiteGraphStore(dbPath string) (*SQLiteGraphStore, error) { if dbPath == "" { dbPath = "/var/lib/memoryweave/graph.db" } + + // 清理 stale WAL/SHM 文件(防止旧进程崩溃后留下这些文件导致锁失败) + // 只有当主 db 文件存在时才清理(避免误删新建库的场景) + if _, err := os.Stat(dbPath); err == nil { + for _, suffix := range []string{"-wal", "-shm", "-journal"} { + f := dbPath + suffix + if _, err := os.Stat(f); err == nil { + os.Remove(f) + } + } + } + cPath := C.CString(dbPath) defer C.free(unsafe.Pointer(cPath)) @@ -43,6 +59,9 @@ func NewSQLiteGraphStore(dbPath string) (*SQLiteGraphStore, error) { return nil, fmt.Errorf("sqlite open graph: %s", msg) } + // 设 10s busy_timeout——等待旧进程/跨进程锁释放,不立即报 "database is locked" + C.sqlite3_busy_timeout(db, 10000) + gs := &SQLiteGraphStore{db: db, path: dbPath} if err := gs.migrate(); err != nil { C.sqlite3_close(db)