diff --git a/internal/store/db.go b/internal/store/db.go index 33bba10..cf55c7f 100644 --- a/internal/store/db.go +++ b/internal/store/db.go @@ -26,11 +26,15 @@ type dbExecer interface { // DB wraps the SQLite database connection. type DB struct { - conn *sql.DB - tx *sql.Tx // current active transaction (nil = no transaction) - path string + conn *sql.DB + tx *sql.Tx // current active transaction (nil = no transaction) + path string + readOnly bool } +// IsReadOnly returns true if the database was opened in read-only mode. +func (db *DB) IsReadOnly() bool { return db.readOnly } + // execer returns the active transaction if set, otherwise the raw connection. func (db *DB) execer() dbExecer { if db.tx != nil { @@ -186,7 +190,7 @@ func OpenReadOnly(dataDir string) (*DB, error) { return nil, fmt.Errorf("open readonly database: %w", err) } conn.SetMaxOpenConns(1) - return &DB{conn: conn, path: dbPath}, nil + return &DB{conn: conn, path: dbPath, readOnly: true}, nil } // Open opens (or creates) the SQLite database at the given directory. diff --git a/internal/store/node.go b/internal/store/node.go index 593afaf..5447430 100644 --- a/internal/store/node.go +++ b/internal/store/node.go @@ -135,7 +135,11 @@ func (db *DB) UpdateEntities(id string, entities []string) error { } // IncrementAccessCount bumps the access count and refreshes last_accessed_at. +// No-op when the database is read-only. func (db *DB) IncrementAccessCount(id string) error { + if db.readOnly { + return nil + } _, err := db.execer().Exec( `UPDATE insights SET access_count = access_count + 1, last_accessed_at = ? WHERE id = ?`, time.Now().UTC().Format(time.RFC3339), id) diff --git a/internal/store/oplog.go b/internal/store/oplog.go index cecbaea..afc07ac 100644 --- a/internal/store/oplog.go +++ b/internal/store/oplog.go @@ -11,7 +11,11 @@ const MaxOplogEntries = 5000 // LogOp records an operation to the oplog and trims old entries beyond MaxOplogEntries. // Best-effort: failures are logged to stderr but do not propagate. +// No-op when the database is read-only. func (db *DB) LogOp(operation, insightID, detail string) { + if db.readOnly { + return + } if _, err := db.execer().Exec( `INSERT INTO oplog (operation, insight_id, detail, created_at) VALUES (?, ?, ?, ?)`, operation, insightID, detail, time.Now().UTC().Format(time.RFC3339)); err != nil {