Documentation
¶
Overview ¶
Package db owns the process-wide SQLite connection lifecycle.
Database access outside schema migrations should go through this package and a DAO. Only this package may open, configure, cache, or close the underlying SQLite connection; table operations belong to internal/dao.
Index ¶
- Constants
- func BeginSQLTx(ctx context.Context, connection *sql.DB, opts *sql.TxOptions) (*sql.Tx, error)
- func BeginTx(ctx context.Context, connection *bun.DB, opts *sql.TxOptions) (bun.Tx, error)
- func BeginWaitStats() (count uint64, total, max time.Duration)
- func BusyRetryStats() (hits uint64, totalWait time.Duration)
- func CanonicalPath(path string) (string, error)
- func Close(path string) error
- func CloseAll() error
- func DSNForOS(path string, windows bool) string
- func IsSchemaIncompatible(err error) bool
- func Open(path string, migrate Migrator) (*bun.DB, error)
- func OpenReadOnlyStandalone(path string) (*bun.DB, error)
- func OpenStandalone(path string, migrate Migrator) (*bun.DB, error)
- func OpenWithOptions(path string, migrate Migrator, opts Options) (*bun.DB, error)
- func Query(path string, migrate Migrator, fn func(*bun.DB) error) error
- func RunInTx(ctx context.Context, connection *bun.DB, opts *sql.TxOptions, ...) error
- func SchemaIncompatible(err error) error
- func SetMigrationRecoveryNotifier(fn func(MigrationRecovery))
- func Write(ctx context.Context, path string, migrate Migrator, ...) error
- type IndexRepair
- type MigrationRecovery
- type Migrator
- type Options
Constants ¶
const BusyTimeout = 10 * time.Second
BusyTimeout is the SQLite busy_timeout applied to every managed connection: a writer waits this long for the single writer lock before returning SQLITE_BUSY. It is the per-statement stall budget that callers which must tolerate transient contention (for example the session runtime heartbeat) need to exceed to absorb one contended begin within a single attempt.
Variables ¶
This section is empty.
Functions ¶
func BeginSQLTx ¶
BeginSQLTx begins a transaction on a raw *sql.DB handle with the same begin retry. Raw-SQL owners (schema initialization and migrations) use it so concurrent startup on one session directory cannot fail on a transient writer conflict.
func BeginTx ¶
BeginTx begins a Bun transaction on a managed (or caller-owned) connection, retrying a transient SQLITE_BUSY/SQLITE_LOCKED begin within the shared budget.
func BeginWaitStats ¶
BeginWaitStats returns the cumulative transaction begin attempt count, the total wall time spent inside begin calls, and the slowest single begin since process start.
func BusyRetryStats ¶
BusyRetryStats returns the cumulative begin-retry hit count and the total backoff time slept between attempts since process start. The wait total counts the scheduled backoff delays only; time blocked inside a begin call (busy_timeout) belongs to the driver and is reported by BeginWaitStats.
func CanonicalPath ¶
CanonicalPath returns the absolute, cleaned database path used as the cache key. Keeping this in one package prevents duplicate connections to the same SQLite file through differently spelled paths.
func Close ¶
Close releases one process-owned SQLite connection. It is used by resource stores that own a whole database file and need to remove that exact file after their data has been deleted. General callers should normally keep using CloseAll at process shutdown.
func CloseAll ¶
func CloseAll() error
CloseAll checkpoints and closes all process-owned connections.
func DSNForOS ¶
DSNForOS returns the configured SQLite file URI with foreign key enforcement disabled, which is the canonical session database policy. It is exported for platform-specific integration tests.
func IsSchemaIncompatible ¶
IsSchemaIncompatible reports whether err was marked by SchemaIncompatible.
func Open ¶
Open returns the process-wide Bun connection for path with foreign key enforcement disabled (the canonical session database policy). Callers must not close it; CloseAll owns the lifecycle. Derived stores that need cascade behavior use OpenWithOptions.
func OpenReadOnlyStandalone ¶
OpenReadOnlyStandalone opens an uncached, read-only connection without running integrity repair, WAL setup, or migrations. It is for safety preflights that must inspect an existing database without changing it. The caller owns the returned connection and must close it.
func OpenStandalone ¶
OpenStandalone opens an uncached connection for callers that explicitly own its lifecycle, such as offline integrity checks. Foreign key enforcement stays disabled to match the canonical session database policy.
func OpenWithOptions ¶
OpenWithOptions returns the process-wide Bun connection for path, applying per-database Options. The connection is cached by canonical path, so the options for a given file must be stable across callers.
func RunInTx ¶
func RunInTx(ctx context.Context, connection *bun.DB, opts *sql.TxOptions, fn func(context.Context, bun.Tx) error) error
RunInTx mirrors (*bun.DB).RunInTx with the shared begin retry: the callback runs in one transaction that is committed on success and rolled back otherwise (including a panic).
func SchemaIncompatible ¶
SchemaIncompatible marks a migration failure caused by a schema this build cannot upgrade in place. internal/db reacts by backing up and rebuilding the database; any other migration error is reported to the caller unchanged.
Migration owners (internal/session) call this for the failures that a rebuild genuinely fixes - an unappliable migration or an incompatible legacy schema - and must not use it for transient or resource failures such as writer contention, cancellation, or a read-only file. internal/db additionally refuses to rebuild for those cases, because rebuilding deletes the database file and must never be triggered by a healthy database under pressure.
func SetMigrationRecoveryNotifier ¶
func SetMigrationRecoveryNotifier(fn func(MigrationRecovery))
SetMigrationRecoveryNotifier registers a hook invoked for every completed recovery, after the recovery has been recorded and logged. Passing nil clears it. It is called once per recovery and must not block: the bus publisher is best-effort and only announces an advisory wake-up.
Types ¶
type IndexRepair ¶
type IndexRepair struct {
// Path is the canonical database path whose indexes were rebuilt.
Path string
// Cause is the integrity-check line that triggered the repair, which names
// the affected index.
Cause string
// At is when the repair happened.
At time.Time
}
IndexRepair records a secondary index internal/db rebuilt while opening a database. An interrupted write can leave an index disagreeing with the table rows it derives from; rebuilding it is lossless, so the open succeeds instead of refusing a database whose canonical pages are intact.
The repair is reported rather than hidden: a database that needed one has already survived a failed write, and front-ends drain these records through TakeIndexRepairs so the user learns about it exactly once.
func TakeIndexRepairs ¶
func TakeIndexRepairs() []IndexRepair
TakeIndexRepairs returns the repairs recorded since the last call and clears them.
func (IndexRepair) Describe ¶
func (r IndexRepair) Describe() string
Describe returns the one-line operator-facing summary of a repair.
type MigrationRecovery ¶
type MigrationRecovery struct {
// Path is the canonical database path that was replaced.
Path string
// BackupPath is the snapshot of the pre-recovery database. It is empty only
// when the database file did not exist and nothing needed to be preserved,
// or when the recovery was performed by another process.
BackupPath string
// Err is the migration failure that triggered the recovery. It is nil for a
// recovery another process announced over the advisory inter-process bus.
Err error
// Peer reports that another process performed the recovery, so the database
// file was replaced while this process may still hold it open.
Peer bool
// At is when the recovery happened.
At time.Time
}
MigrationRecovery records a schema migration failure that internal/db recovered from by snapshotting the unrecoverable database and starting a new empty one in its place.
The previous data is not deleted: it stays in BackupPath, which callers should surface to the user (front-ends drain the records with TakeMigrationRecoveries so the notice is shown exactly once).
func MigrationRecoveries ¶
func MigrationRecoveries() []MigrationRecovery
MigrationRecoveries returns the recoveries recorded in this process without clearing them.
func TakeMigrationRecoveries ¶
func TakeMigrationRecoveries() []MigrationRecovery
TakeMigrationRecoveries returns the recoveries recorded since the last call and clears them, so a front-end can tell the user exactly once.
func (MigrationRecovery) Describe ¶
func (r MigrationRecovery) Describe() string
Describe returns the one-line operator-facing summary of a recovery. Callers that want a richer message use the fields directly.
type Migrator ¶
Migrator initializes or validates a database. It is intentionally kept compatible with the existing session migration implementation; migrations are the one place where schema SQL is required.
type Options ¶
type Options struct {
ForeignKeys bool
}
Options configures per-database SQLite connection behavior.
ForeignKeys enables SQLite foreign key enforcement for one database file. The canonical session database must keep it disabled: project policy enforces referential integrity in the repository layer (transactional writes, centralized deletion cleanup lists, and integrity tests such as TestDeleteSessionRemovesEveryChildRow), not in the database engine, so that cross-version recovery and partially corrupted canonical stores are never amplified by hard constraints.
A private, rebuildable derived store may opt in. The per-knowledge-base graph/FTS database (see docs/proposal/desktop-knowledge-base-agent-proposal.md) designs its snapshot lifecycle around ON DELETE CASCADE pruning and can always be rebuilt from its source directory, so it enables enforcement without exposing canonical session data to it. Options must be consistent for a given file path because connections are cached per path.