db

package
v1.3.104 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 19 Imported by: 0

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

View Source
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

func BeginSQLTx(ctx context.Context, connection *sql.DB, opts *sql.TxOptions) (*sql.Tx, error)

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

func BeginTx(ctx context.Context, connection *bun.DB, opts *sql.TxOptions) (bun.Tx, error)

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 BeginWaitQuantiles added in v1.3.103

func BeginWaitQuantiles() (p50, p99 time.Duration)

BeginWaitQuantiles returns bucket-approximated p50 and p99 transaction begin waits. A quantile in a bounded bucket reports that bucket's inclusive upper bound, so the value is never an understatement; a quantile in the overflow bucket (a single begin slower than the last bound) reports the observed maximum rather than the last bound, so the slow tail is not understated either. Both are zero until the first begin is recorded.

func BeginWaitStats

func BeginWaitStats() (count uint64, total, max time.Duration)

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

func BusyRetryStats() (hits uint64, totalWait time.Duration)

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

func CanonicalPath(path string) (string, error)

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 CheckpointStats added in v1.3.103

func CheckpointStats() (attempts, failures uint64, busyFrames, logFrames, checkpointed int64)

CheckpointStats returns the cumulative checkpoint attempt/failure counts and the accumulated (busy, log, checkpointed) frame counts since process start.

func Close

func Close(path string) error

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

func DSNForOS(path string, windows bool) string

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 IsCached added in v1.3.103

func IsCached(path string) bool

IsCached reports whether this process currently holds a cached connection for the database file at path. Advisory consumers (the UDP lease bus database_rebuilt watcher) use it to ignore notices for files they never opened, so a forged or stale packet cannot trigger a close/checkpoint of an unrelated database.

func IsSchemaIncompatible

func IsSchemaIncompatible(err error) bool

IsSchemaIncompatible reports whether err was marked by SchemaIncompatible.

func Open

func Open(path string, migrate Migrator) (*bun.DB, error)

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

func OpenReadOnlyStandalone(path string) (*bun.DB, error)

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

func OpenStandalone(path string, migrate Migrator) (*bun.DB, error)

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

func OpenWithOptions(path string, migrate Migrator, opts Options) (*bun.DB, error)

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 Query

func Query(path string, migrate Migrator, fn func(*bun.DB) error) error

Query runs a read operation through the process-wide connection.

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

func SchemaIncompatible(err error) error

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.

func Write

func Write(ctx context.Context, path string, migrate Migrator, fn func(context.Context, bun.Tx) error) error

Write runs a write operation in one Bun transaction.

Types

type DatabasePoolStat added in v1.3.103

type DatabasePoolStat struct {
	Path               string `json:"path"`
	MaxOpenConnections int    `json:"maxOpenConnections"`
	OpenConnections    int    `json:"openConnections"`
	InUse              int    `json:"inUse"`
	Idle               int    `json:"idle"`
	WaitCount          int64  `json:"waitCount"`
	WaitDurationMillis int64  `json:"waitDurationMs"`
	MaxIdleClosed      int64  `json:"maxIdleClosed"`
	MaxIdleTimeClosed  int64  `json:"maxIdleTimeClosed"`
	MaxLifetimeClosed  int64  `json:"maxLifetimeClosed"`
}

DatabasePoolStat reports one open database's connection-pool counters. Every managed connection uses SetMaxOpenConns(1), so WaitCount/WaitDuration is the direct measure of how often and how long a transaction or query had to queue for the single connection: a growing value under concurrent sessions is the baseline that would justify (or rule out) a separate read connection pool. Path is the database file's base name so the local /debug/vars surface does not expose absolute filesystem paths.

func PoolStats added in v1.3.103

func PoolStats() []DatabasePoolStat

PoolStats reports the connection-pool counters for every database this process currently holds open, sorted by path. It is the measurement half of deciding whether the single-writer connection model needs a read pool; it changes no behavior.

type DatabaseWalStat added in v1.3.103

type DatabaseWalStat struct {
	Path     string `json:"path"`
	WalBytes int64  `json:"walBytes"`
}

DatabaseWalStat reports one cached database's on-disk write-ahead log size. Path is the database file's base name: the /debug/vars endpoint is a local diagnostic surface, so it does not expose absolute filesystem paths.

func WalStats added in v1.3.103

func WalStats() []DatabaseWalStat

WalStats reports the write-ahead log size for every database this process currently holds open. A WAL that grows without shrinking between checkpoints is the direct signal that write pressure outpaces checkpointing.

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

type Migrator func(*sql.DB) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL