[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/store/RFC.md fully. Find ONE featur... #107

Merged
Virgil merged 1 commit from agent/read---spec-code-core-go-store-rfc-md-fu into dev 2026-04-04 09:05:08 +00:00
11 changed files with 98 additions and 98 deletions

View file

@ -32,7 +32,7 @@ func (storeInstance *Store) Compact(options CompactOptions) core.Result {
if err := storeInstance.ensureReady("store.Compact"); err != nil {
return core.Result{Value: err, OK: false}
}
if err := ensureJournalSchema(storeInstance.database); err != nil {
if err := ensureJournalSchema(storeInstance.sqliteDatabase); err != nil {
return core.Result{Value: core.E("store.Compact", "ensure journal schema", err), OK: false}
}
@ -53,7 +53,7 @@ func (storeInstance *Store) Compact(options CompactOptions) core.Result {
return core.Result{Value: core.E("store.Compact", "ensure archive directory", result.Value.(error)), OK: false}
}
rows, err := storeInstance.database.Query(
rows, err := storeInstance.sqliteDatabase.Query(
"SELECT entry_id, bucket_name, measurement, fields_json, tags_json, committed_at FROM "+journalEntriesTableName+" WHERE archived_at IS NULL AND committed_at < ? ORDER BY committed_at",
options.Before.UnixMilli(),
)
@ -134,7 +134,7 @@ func (storeInstance *Store) Compact(options CompactOptions) core.Result {
}
fileClosed = true
transaction, err := storeInstance.database.Begin()
transaction, err := storeInstance.sqliteDatabase.Begin()
if err != nil {
return core.Result{Value: core.E("store.Compact", "begin archive transaction", err), OK: false}
}

View file

@ -27,7 +27,7 @@ func TestCompact_Compact_Good_GzipArchive(t *testing.T) {
storeInstance.CommitToJournal("session-b", map[string]any{"like": 2}, map[string]string{"workspace": "session-b"}).OK,
)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Now().Add(-48*time.Hour).UnixMilli(),
"session-a",
@ -76,7 +76,7 @@ func TestCompact_Compact_Good_ZstdArchive(t *testing.T) {
storeInstance.CommitToJournal("session-a", map[string]any{"like": 1}, map[string]string{"workspace": "session-a"}).OK,
)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Now().Add(-48*time.Hour).UnixMilli(),
"session-a",

View file

@ -54,20 +54,20 @@ func TestCoverage_GetAll_Bad_ScanError(t *testing.T) {
require.NoError(t, storeInstance.Set("g", "good", "value"))
// Restructure the table to allow NULLs, then insert a NULL-key row.
_, err = storeInstance.database.Exec("ALTER TABLE entries RENAME TO entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("ALTER TABLE entries RENAME TO entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec(`CREATE TABLE entries (
_, err = storeInstance.sqliteDatabase.Exec(`CREATE TABLE entries (
group_name TEXT,
entry_key TEXT,
entry_value TEXT,
expires_at INTEGER
)`)
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries SELECT * FROM entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries SELECT * FROM entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES ('g', NULL, 'null-key-val')")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES ('g', NULL, 'null-key-val')")
require.NoError(t, err)
_, err = storeInstance.database.Exec("DROP TABLE entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("DROP TABLE entries_backup")
require.NoError(t, err)
_, err = storeInstance.GetAll("g")
@ -146,20 +146,20 @@ func TestCoverage_Render_Bad_ScanError(t *testing.T) {
require.NoError(t, storeInstance.Set("g", "good", "value"))
_, err = storeInstance.database.Exec("ALTER TABLE entries RENAME TO entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("ALTER TABLE entries RENAME TO entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec(`CREATE TABLE entries (
_, err = storeInstance.sqliteDatabase.Exec(`CREATE TABLE entries (
group_name TEXT,
entry_key TEXT,
entry_value TEXT,
expires_at INTEGER
)`)
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries SELECT * FROM entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries SELECT * FROM entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES ('g', NULL, 'null-key-val')")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES ('g', NULL, 'null-key-val')")
require.NoError(t, err)
_, err = storeInstance.database.Exec("DROP TABLE entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("DROP TABLE entries_backup")
require.NoError(t, err)
_, err = storeInstance.Render("{{ .good }}", "g")
@ -231,20 +231,20 @@ func TestCoverage_GroupsSeq_Bad_ScanError(t *testing.T) {
require.NoError(t, err)
defer storeInstance.Close()
_, err = storeInstance.database.Exec("ALTER TABLE entries RENAME TO entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("ALTER TABLE entries RENAME TO entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec(`CREATE TABLE entries (
_, err = storeInstance.sqliteDatabase.Exec(`CREATE TABLE entries (
group_name TEXT,
entry_key TEXT,
entry_value TEXT,
expires_at INTEGER
)`)
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries SELECT * FROM entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries SELECT * FROM entries_backup")
require.NoError(t, err)
_, err = storeInstance.database.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES (NULL, 'k', 'v')")
_, err = storeInstance.sqliteDatabase.Exec("INSERT INTO entries (group_name, entry_key, entry_value) VALUES (NULL, 'k', 'v')")
require.NoError(t, err)
_, err = storeInstance.database.Exec("DROP TABLE entries_backup")
_, err = storeInstance.sqliteDatabase.Exec("DROP TABLE entries_backup")
require.NoError(t, err)
for groupName, iterationErr := range storeInstance.GroupsSeq("") {
@ -265,8 +265,8 @@ func TestCoverage_GroupsSeq_Bad_RowsError(t *testing.T) {
defer database.Close()
storeInstance := &Store{
database: database,
cancelPurge: func() {},
sqliteDatabase: database,
cancelPurge: func() {},
}
for groupName, iterationErr := range storeInstance.GroupsSeq("") {
@ -305,8 +305,8 @@ func TestCoverage_ScopedStore_Bad_GroupsSeqRowsError(t *testing.T) {
scopedStore := &ScopedStore{
backingStore: &Store{
database: database,
cancelPurge: func() {},
sqliteDatabase: database,
cancelPurge: func() {},
},
namespace: "tenant-a",
}

View file

@ -58,7 +58,7 @@ func (storeInstance *Store) CommitToJournal(measurement string, fields map[strin
if tags == nil {
tags = map[string]string{}
}
if err := ensureJournalSchema(storeInstance.database); err != nil {
if err := ensureJournalSchema(storeInstance.sqliteDatabase); err != nil {
return core.Result{Value: core.E("store.CommitToJournal", "ensure journal schema", err), OK: false}
}
@ -73,7 +73,7 @@ func (storeInstance *Store) CommitToJournal(measurement string, fields map[strin
committedAt := time.Now().UnixMilli()
if err := insertJournalEntry(
storeInstance.database,
storeInstance.sqliteDatabase,
storeInstance.journalBucket(),
measurement,
fieldsJSON,
@ -102,7 +102,7 @@ func (storeInstance *Store) QueryJournal(flux string) core.Result {
if err := storeInstance.ensureReady("store.QueryJournal"); err != nil {
return core.Result{Value: err, OK: false}
}
if err := ensureJournalSchema(storeInstance.database); err != nil {
if err := ensureJournalSchema(storeInstance.sqliteDatabase); err != nil {
return core.Result{Value: core.E("store.QueryJournal", "ensure journal schema", err), OK: false}
}
@ -132,7 +132,7 @@ func isRawSQLJournalQuery(query string) bool {
}
func (storeInstance *Store) queryJournalRows(query string, arguments ...any) core.Result {
rows, err := storeInstance.database.Query(query, arguments...)
rows, err := storeInstance.sqliteDatabase.Query(query, arguments...)
if err != nil {
return core.Result{Value: core.E("store.QueryJournal", "query rows", err), OK: false}
}

View file

@ -136,7 +136,7 @@ func TestJournal_QueryJournal_Good_BucketFilter(t *testing.T) {
storeInstance.CommitToJournal("session-a", map[string]any{"like": 1}, map[string]string{"workspace": "session-a"}).OK,
)
require.NoError(t, insertJournalEntry(
storeInstance.database,
storeInstance.sqliteDatabase,
"events",
"session-b",
`{"like":2}`,
@ -165,13 +165,13 @@ func TestJournal_QueryJournal_Good_AbsoluteRangeWithStop(t *testing.T) {
storeInstance.CommitToJournal("session-b", map[string]any{"like": 2}, map[string]string{"workspace": "session-b"}).OK,
)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Date(2026, 3, 29, 12, 0, 0, 0, time.UTC).UnixMilli(),
"session-a",
)
require.NoError(t, err)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Date(2026, 3, 30, 12, 0, 0, 0, time.UTC).UnixMilli(),
"session-b",
@ -198,13 +198,13 @@ func TestJournal_QueryJournal_Good_AbsoluteRangeHonoursStop(t *testing.T) {
storeInstance.CommitToJournal("session-b", map[string]any{"like": 2}, map[string]string{"workspace": "session-b"}).OK,
)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Date(2026, 3, 29, 12, 0, 0, 0, time.UTC).UnixMilli(),
"session-a",
)
require.NoError(t, err)
_, err = storeInstance.database.Exec(
_, err = storeInstance.sqliteDatabase.Exec(
"UPDATE "+journalEntriesTableName+" SET committed_at = ? WHERE measurement = ?",
time.Date(2026, 3, 30, 12, 0, 0, 0, time.UTC).UnixMilli(),
"session-b",

View file

@ -588,8 +588,8 @@ func TestScope_Quota_Bad_QuotaCheckQueryError(t *testing.T) {
defer database.Close()
storeInstance := &Store{
database: database,
cancelPurge: func() {},
sqliteDatabase: database,
cancelPurge: func() {},
}
scopedStore, err := NewScopedWithQuota(storeInstance, "tenant-a", QuotaConfig{MaxKeys: 1})
@ -895,7 +895,7 @@ func rawEntryCount(tb testing.TB, storeInstance *Store, group string) int {
tb.Helper()
var count int
err := storeInstance.database.QueryRow(
err := storeInstance.sqliteDatabase.QueryRow(
"SELECT COUNT(*) FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ?",
group,
).Scan(&count)

View file

@ -60,7 +60,7 @@ type JournalConfiguration struct {
// Usage example: `storeInstance, err := store.New(":memory:")`
type Store struct {
database *sql.DB
sqliteDatabase *sql.DB
databasePath string
purgeContext context.Context
cancelPurge context.CancelFunc
@ -85,7 +85,7 @@ func (storeInstance *Store) ensureReady(operation string) error {
if storeInstance == nil {
return core.E(operation, "store is nil", nil)
}
if storeInstance.database == nil {
if storeInstance.sqliteDatabase == nil {
return core.E(operation, "store is not initialised", nil)
}
@ -242,12 +242,12 @@ func openSQLiteStore(operation, databasePath string) (*Store, error) {
purgeContext, cancel := context.WithCancel(context.Background())
return &Store{
database: sqliteDatabase,
databasePath: databasePath,
purgeContext: purgeContext,
cancelPurge: cancel,
purgeInterval: 60 * time.Second,
watchers: make(map[string][]chan Event),
sqliteDatabase: sqliteDatabase,
databasePath: databasePath,
purgeContext: purgeContext,
cancelPurge: cancel,
purgeInterval: 60 * time.Second,
watchers: make(map[string][]chan Event),
}, nil
}
@ -293,10 +293,10 @@ func (storeInstance *Store) Close() error {
storeInstance.orphanWorkspaces = nil
storeInstance.orphanWorkspacesLock.Unlock()
if storeInstance.database == nil {
if storeInstance.sqliteDatabase == nil {
return orphanCleanupErr
}
if err := storeInstance.database.Close(); err != nil {
if err := storeInstance.sqliteDatabase.Close(); err != nil {
return core.E("store.Close", "database close", err)
}
return orphanCleanupErr
@ -310,7 +310,7 @@ func (storeInstance *Store) Get(group, key string) (string, error) {
var value string
var expiresAt sql.NullInt64
err := storeInstance.database.QueryRow(
err := storeInstance.sqliteDatabase.QueryRow(
"SELECT "+entryValueColumn+", expires_at FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND "+entryKeyColumn+" = ?",
group, key,
).Scan(&value, &expiresAt)
@ -335,7 +335,7 @@ func (storeInstance *Store) Set(group, key, value string) error {
return err
}
_, err := storeInstance.database.Exec(
_, err := storeInstance.sqliteDatabase.Exec(
"INSERT INTO "+entriesTableName+" ("+entryGroupColumn+", "+entryKeyColumn+", "+entryValueColumn+", expires_at) VALUES (?, ?, ?, NULL) "+
"ON CONFLICT("+entryGroupColumn+", "+entryKeyColumn+") DO UPDATE SET "+entryValueColumn+" = excluded."+entryValueColumn+", expires_at = NULL",
group, key, value,
@ -354,7 +354,7 @@ func (storeInstance *Store) SetWithTTL(group, key, value string, timeToLive time
}
expiresAt := time.Now().Add(timeToLive).UnixMilli()
_, err := storeInstance.database.Exec(
_, err := storeInstance.sqliteDatabase.Exec(
"INSERT INTO "+entriesTableName+" ("+entryGroupColumn+", "+entryKeyColumn+", "+entryValueColumn+", expires_at) VALUES (?, ?, ?, ?) "+
"ON CONFLICT("+entryGroupColumn+", "+entryKeyColumn+") DO UPDATE SET "+entryValueColumn+" = excluded."+entryValueColumn+", expires_at = excluded.expires_at",
group, key, value, expiresAt,
@ -372,7 +372,7 @@ func (storeInstance *Store) Delete(group, key string) error {
return err
}
deleteResult, err := storeInstance.database.Exec("DELETE FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND "+entryKeyColumn+" = ?", group, key)
deleteResult, err := storeInstance.sqliteDatabase.Exec("DELETE FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND "+entryKeyColumn+" = ?", group, key)
if err != nil {
return core.E("store.Delete", "delete row", err)
}
@ -393,7 +393,7 @@ func (storeInstance *Store) Count(group string) (int, error) {
}
var count int
err := storeInstance.database.QueryRow(
err := storeInstance.sqliteDatabase.QueryRow(
"SELECT COUNT(*) FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND (expires_at IS NULL OR expires_at > ?)",
group, time.Now().UnixMilli(),
).Scan(&count)
@ -409,7 +409,7 @@ func (storeInstance *Store) DeleteGroup(group string) error {
return err
}
deleteResult, err := storeInstance.database.Exec("DELETE FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ?", group)
deleteResult, err := storeInstance.sqliteDatabase.Exec("DELETE FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ?", group)
if err != nil {
return core.E("store.DeleteGroup", "delete group", err)
}
@ -432,11 +432,11 @@ func (storeInstance *Store) DeletePrefix(groupPrefix string) error {
var rows *sql.Rows
var err error
if groupPrefix == "" {
rows, err = storeInstance.database.Query(
rows, err = storeInstance.sqliteDatabase.Query(
"SELECT DISTINCT " + entryGroupColumn + " FROM " + entriesTableName + " ORDER BY " + entryGroupColumn,
)
} else {
rows, err = storeInstance.database.Query(
rows, err = storeInstance.sqliteDatabase.Query(
"SELECT DISTINCT "+entryGroupColumn+" FROM "+entriesTableName+" WHERE "+entryGroupColumn+" LIKE ? ESCAPE '^' ORDER BY "+entryGroupColumn,
escapeLike(groupPrefix)+"%",
)
@ -501,7 +501,7 @@ func (storeInstance *Store) GetPage(group string, offset, limit int) ([]KeyValue
return nil, core.E("store.GetPage", "limit must be zero or positive", nil)
}
rows, err := storeInstance.database.Query(
rows, err := storeInstance.sqliteDatabase.Query(
"SELECT "+entryKeyColumn+", "+entryValueColumn+" FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY "+entryKeyColumn+" LIMIT ? OFFSET ?",
group, time.Now().UnixMilli(), limit, offset,
)
@ -532,7 +532,7 @@ func (storeInstance *Store) AllSeq(group string) iter.Seq2[KeyValue, error] {
return
}
rows, err := storeInstance.database.Query(
rows, err := storeInstance.sqliteDatabase.Query(
"SELECT "+entryKeyColumn+", "+entryValueColumn+" FROM "+entriesTableName+" WHERE "+entryGroupColumn+" = ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY "+entryKeyColumn,
group, time.Now().UnixMilli(),
)
@ -625,12 +625,12 @@ func (storeInstance *Store) CountAll(groupPrefix string) (int, error) {
var count int
var err error
if groupPrefix == "" {
err = storeInstance.database.QueryRow(
err = storeInstance.sqliteDatabase.QueryRow(
"SELECT COUNT(*) FROM "+entriesTableName+" WHERE (expires_at IS NULL OR expires_at > ?)",
time.Now().UnixMilli(),
).Scan(&count)
} else {
err = storeInstance.database.QueryRow(
err = storeInstance.sqliteDatabase.QueryRow(
"SELECT COUNT(*) FROM "+entriesTableName+" WHERE "+entryGroupColumn+" LIKE ? ESCAPE '^' AND (expires_at IS NULL OR expires_at > ?)",
escapeLike(groupPrefix)+"%", time.Now().UnixMilli(),
).Scan(&count)
@ -672,12 +672,12 @@ func (storeInstance *Store) GroupsSeq(groupPrefix ...string) iter.Seq2[string, e
var err error
now := time.Now().UnixMilli()
if actualGroupPrefix == "" {
rows, err = storeInstance.database.Query(
rows, err = storeInstance.sqliteDatabase.Query(
"SELECT DISTINCT "+entryGroupColumn+" FROM "+entriesTableName+" WHERE (expires_at IS NULL OR expires_at > ?) ORDER BY "+entryGroupColumn,
now,
)
} else {
rows, err = storeInstance.database.Query(
rows, err = storeInstance.sqliteDatabase.Query(
"SELECT DISTINCT "+entryGroupColumn+" FROM "+entriesTableName+" WHERE "+entryGroupColumn+" LIKE ? ESCAPE '^' AND (expires_at IS NULL OR expires_at > ?) ORDER BY "+entryGroupColumn,
escapeLike(actualGroupPrefix)+"%", now,
)
@ -818,12 +818,12 @@ func (storeInstance *Store) purgeExpiredMatchingGroupPrefix(groupPrefix string)
)
now := time.Now().UnixMilli()
if groupPrefix == "" {
deleteResult, err = storeInstance.database.Exec(
deleteResult, err = storeInstance.sqliteDatabase.Exec(
"DELETE FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ?",
now,
)
} else {
deleteResult, err = storeInstance.database.Exec(
deleteResult, err = storeInstance.sqliteDatabase.Exec(
"DELETE FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ? AND "+entryGroupColumn+" LIKE ? ESCAPE '^'",
now, escapeLike(groupPrefix)+"%",
)

View file

@ -93,7 +93,7 @@ func TestStore_New_Good_WALMode(t *testing.T) {
defer storeInstance.Close()
var mode string
err = storeInstance.database.QueryRow("PRAGMA journal_mode").Scan(&mode)
err = storeInstance.sqliteDatabase.QueryRow("PRAGMA journal_mode").Scan(&mode)
require.NoError(t, err)
assert.Equal(t, "wal", mode, "journal_mode should be WAL")
}
@ -840,8 +840,8 @@ func TestStore_Close_Good_OperationsFailAfterClose(t *testing.T) {
func TestStore_Close_Bad_DriverCloseError(t *testing.T) {
database := testCloseErrorDatabase(t)
storeInstance := &Store{
database: database,
cancelPurge: func() {},
sqliteDatabase: database,
cancelPurge: func() {},
}
err := storeInstance.Close()
@ -1400,8 +1400,8 @@ func TestStore_PurgeExpired_Bad_ClosedStore(t *testing.T) {
func TestStore_PurgeExpired_Bad_RowsAffectedError(t *testing.T) {
database := testRowsAffectedErrorDatabase(t)
storeInstance := &Store{
database: database,
cancelPurge: func() {},
sqliteDatabase: database,
cancelPurge: func() {},
}
_, err := storeInstance.PurgeExpired()
@ -1423,7 +1423,7 @@ func TestStore_PurgeExpired_Good_BackgroundPurge(t *testing.T) {
// The expired key should have been removed by the background goroutine.
// Use a raw query to check the row is actually gone (not just filtered by Get).
var count int
err = storeInstance.database.QueryRow("SELECT COUNT(*) FROM entries WHERE group_name = ?", "g").Scan(&count)
err = storeInstance.sqliteDatabase.QueryRow("SELECT COUNT(*) FROM entries WHERE group_name = ?", "g").Scan(&count)
require.NoError(t, err)
assert.Equal(t, 1, count, "background purge should have deleted the expired row")
}

View file

@ -23,7 +23,7 @@ func (storeInstance *Store) Transaction(operation func(*StoreTransaction) error)
return core.E("store.Transaction", "operation is nil", nil)
}
transaction, err := storeInstance.database.Begin()
transaction, err := storeInstance.sqliteDatabase.Begin()
if err != nil {
return core.E("store.Transaction", "begin transaction", err)
}

View file

@ -37,11 +37,11 @@ var defaultWorkspaceStateDirectory = ".core/state/"
//
// Usage example: `workspace, err := storeInstance.NewWorkspace("scroll-session-2026-03-30"); if err != nil { return }; defer workspace.Discard(); _ = workspace.Put("like", map[string]any{"user": "@alice"})`
type Workspace struct {
name string
backingStore *Store
database *sql.DB
databasePath string
filesystem *core.Fs
name string
backingStore *Store
workspaceDatabase *sql.DB
databasePath string
filesystem *core.Fs
closeLock sync.Mutex
closed bool
@ -78,7 +78,7 @@ func (workspace *Workspace) ensureReady(operation string) error {
if workspace.backingStore == nil {
return core.E(operation, "workspace store is nil", nil)
}
if workspace.database == nil {
if workspace.workspaceDatabase == nil {
return core.E(operation, "workspace database is nil", nil)
}
if workspace.filesystem == nil {
@ -127,11 +127,11 @@ func (storeInstance *Store) NewWorkspace(name string) (*Workspace, error) {
}
return &Workspace{
name: name,
backingStore: storeInstance,
database: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
name: name,
backingStore: storeInstance,
workspaceDatabase: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
}, nil
}
@ -186,11 +186,11 @@ func discoverOrphanWorkspaces(stateDirectory string, backingStore *Store) []*Wor
continue
}
orphanWorkspaces = append(orphanWorkspaces, &Workspace{
name: workspaceNameFromPath(stateDirectory, databasePath),
backingStore: backingStore,
database: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
name: workspaceNameFromPath(stateDirectory, databasePath),
backingStore: backingStore,
workspaceDatabase: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
})
}
return orphanWorkspaces
@ -238,11 +238,11 @@ func (storeInstance *Store) RecoverOrphans(stateDirectory string) []*Workspace {
continue
}
orphanWorkspaces = append(orphanWorkspaces, &Workspace{
name: workspaceNameFromPath(stateDirectory, databasePath),
backingStore: storeInstance,
database: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
name: workspaceNameFromPath(stateDirectory, databasePath),
backingStore: storeInstance,
workspaceDatabase: workspaceDatabase,
databasePath: databasePath,
filesystem: filesystem,
})
}
return orphanWorkspaces
@ -266,7 +266,7 @@ func (workspace *Workspace) Put(kind string, data map[string]any) error {
return err
}
_, err = workspace.database.Exec(
_, err = workspace.workspaceDatabase.Exec(
"INSERT INTO "+workspaceEntriesTableName+" (entry_kind, entry_data, created_at) VALUES (?, ?, ?)",
kind,
dataJSON,
@ -327,7 +327,7 @@ func (workspace *Workspace) Query(sqlQuery string) core.Result {
return core.Result{Value: err, OK: false}
}
rows, err := workspace.database.Query(sqlQuery)
rows, err := workspace.workspaceDatabase.Query(sqlQuery)
if err != nil {
return core.Result{Value: core.E("store.Workspace.Query", "query workspace", err), OK: false}
}
@ -345,7 +345,7 @@ func (workspace *Workspace) aggregateFields() (map[string]any, error) {
return nil, err
}
rows, err := workspace.database.Query(
rows, err := workspace.workspaceDatabase.Query(
"SELECT entry_kind, COUNT(*) FROM " + workspaceEntriesTableName + " GROUP BY entry_kind ORDER BY entry_kind",
)
if err != nil {
@ -384,7 +384,7 @@ func (workspace *Workspace) closeAndCleanup(removeFiles bool) error {
if workspace == nil {
return nil
}
if workspace.database == nil || workspace.filesystem == nil {
if workspace.workspaceDatabase == nil || workspace.filesystem == nil {
return nil
}
@ -396,7 +396,7 @@ func (workspace *Workspace) closeAndCleanup(removeFiles bool) error {
}
workspace.closed = true
if err := workspace.database.Close(); err != nil {
if err := workspace.workspaceDatabase.Close(); err != nil {
return core.E("store.Workspace.closeAndRemoveFiles", "close workspace database", err)
}
if !removeFiles {
@ -414,11 +414,11 @@ func (storeInstance *Store) commitWorkspaceAggregate(workspaceName string, field
if err := storeInstance.ensureReady("store.Workspace.Commit"); err != nil {
return err
}
if err := ensureJournalSchema(storeInstance.database); err != nil {
if err := ensureJournalSchema(storeInstance.sqliteDatabase); err != nil {
return core.E("store.Workspace.Commit", "ensure journal schema", err)
}
transaction, err := storeInstance.database.Begin()
transaction, err := storeInstance.sqliteDatabase.Begin()
if err != nil {
return core.E("store.Workspace.Commit", "begin transaction", err)
}

View file

@ -213,7 +213,7 @@ func TestWorkspace_RecoverOrphans_Good(t *testing.T) {
workspace, err := storeInstance.NewWorkspace("orphan-session")
require.NoError(t, err)
require.NoError(t, workspace.Put("like", map[string]any{"user": "@alice"}))
require.NoError(t, workspace.database.Close())
require.NoError(t, workspace.workspaceDatabase.Close())
orphans := storeInstance.RecoverOrphans(stateDirectory)
require.Len(t, orphans, 1)