Documentation
¶
Overview ¶
Package sqlite provides a SQLite implementation of store.Store using grove ORM.
Index ¶
- Constants
- Variables
- func DSN(path string) string
- type Store
- func (s *Store) BusyTimeout(ctx context.Context) (time.Duration, error)
- func (s *Store) Close() error
- func (s *Store) DB() *grove.DB
- func (s *Store) Keys() key.Store
- func (s *Store) Migrate(ctx context.Context) error
- func (s *Store) Ping(ctx context.Context) error
- func (s *Store) Policies() policy.Store
- func (s *Store) Rotations() rotation.Store
- func (s *Store) Scopes() scope.Store
- func (s *Store) Usages() usage.Store
Constants ¶
const BusyTimeout = 5 * time.Second
BusyTimeout is how long a connection opened with DSN waits for another connection's write lock before it gives up with SQLITE_BUSY.
Variables ¶
var Migrations = migrate.NewGroup("keysmith")
Migrations is the grove migration group for the Keysmith SQLite store. Each migration lives in a file of its own, named <14 digit version>_<name>.go, and registers itself with Migrations.Add.
Store.Migrate runs the group through grove's orchestrator, which takes the migration lock first. A host that runs its migrations centrally can register this group with its own orchestrator instead and turn Store.Migrate off (the Forge extension's WithDisableMigrate).
The versions and names match the ones keysmith has always recorded in grove_migrations, so a database that already applied them skips them.
Functions ¶
func DSN ¶
DSN returns the data source name to open the database at path with, for sqlitedriver.SqliteDB.Open. Open the database you hand to New with it:
sdb := sqlitedriver.New()
err := sdb.Open(ctx, sqlite.DSN("keysmith.db"))
database/sql pools connections and every pooled connection has its own settings, so the DSN is the one place that reaches all of them. Grove's driver runs PRAGMA foreign_keys=ON once at Open, on whichever connection it gets, and sets no busy timeout. DSN adds three settings, applied by modernc.org/sqlite to each connection it opens:
- busy_timeout: a write waits up to BusyTimeout for the write lock. The engine's ValidateKey updates last_used_at in the background, so the next write regularly finds the lock taken.
- foreign_keys: ON DELETE CASCADE holds on every connection, so deleting a key or a scope never leaves keysmith_key_scopes rows behind.
- _txlock=immediate: transactions take the write lock at BEGIN. SQLite skips the busy timeout when a transaction that has already read tries to write, which AssignToKey does, and fails at once with SQLITE_BUSY. Read-only transactions still begin deferred.
path is a file name or a file: URI. Query parameters already on it are kept, and so is any of the three settings it already sets: the caller's _txlock, busy_timeout or foreign_keys wins, and DSN adds only the ones that are missing. If you open the database some other way, such as from a grove extension's config, put the same three parameters on that DSN.
Types ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store implements store.Store using SQLite via Grove ORM.
func (*Store) BusyTimeout ¶
BusyTimeout reads PRAGMA busy_timeout on one pooled connection. Grove's driver never sets a busy timeout, so zero means the DSN didn't set one either, and then no connection in the pool has it. The extension reads it at startup to warn about a database opened without DSN.
func (*Store) Migrate ¶
Migrate applies the pending migrations in Migrations through grove's orchestrator, which holds grove's migration lock (a row in grove_migration_locks) while it runs.
Source Files
¶
- 20240101000001_create_keys.go
- 20240101000002_create_policies.go
- 20240101000003_create_scopes.go
- 20240101000004_create_usage.go
- 20240101000005_create_rotations.go
- 20260930000001_rotation_hints_and_old_hash_index.go
- 20260930000002_drop_usage_agg.go
- 20260930000003_close_legacy_grace.go
- 20261007000001_key_version.go
- doc.go
- dsn.go
- key.go
- migrations.go
- models.go
- policy.go
- rotation.go
- scope.go
- store.go
- usage.go