// Package db opens the SQLite database and holds the query layer. package db import ( "context" "database/sql" _ "embed" "fmt" _ "modernc.org/sqlite" ) //go:embed schema.sql var Schema string // DB wraps *sql.DB. Other packages may run raw SQL through it. type DB struct { *sql.DB } // Open opens (or creates) the database, applies schema.sql and migrations. func Open(path string) (*DB, error) { sqlDB, err := sql.Open("sqlite", path+"?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)") if err != nil { return nil, err } // SQLite allows one writer. A single connection avoids SQLITE_BUSY // between goroutines; busy_timeout covers external writers. sqlDB.SetMaxOpenConns(1) d := &DB{sqlDB} if _, err := d.ExecContext(context.Background(), Schema); err != nil { return nil, fmt.Errorf("apply schema: %w", err) } if err := d.migrate(context.Background()); err != nil { return nil, fmt.Errorf("migrate: %w", err) } return d, nil }