fix(graph_sqlite): add busy_timeout + stale WAL/SHM cleanup on startup
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
This commit is contained in:
parent
cd49a2801a
commit
daabd54649
|
|
@ -7,12 +7,16 @@ package governance
|
|||
#cgo LDFLAGS: -lsqlite3
|
||||
#include <sqlite3.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue