package db import ( "context" "database/sql" "fmt" "os" "path/filepath" _ "github.com/mattn/go-sqlite3" ) const sqliteDriverName = "sqlite3" func Open(ctx context.Context, sqlitePath string) (*sql.DB, error) { if sqlitePath == "" { return nil, fmt.Errorf("sqlite path is required") } if err := os.MkdirAll(filepath.Dir(sqlitePath), 0o750); err != nil { return nil, fmt.Errorf("create sqlite dir: %w", err) } database, err := sql.Open(sqliteDriverName, sqlitePath) if err != nil { return nil, fmt.Errorf("open sqlite database: %w", err) } database.SetMaxOpenConns(1) database.SetMaxIdleConns(1) if err := applyPragmas(ctx, database); err != nil { database.Close() return nil, err } if err := database.PingContext(ctx); err != nil { database.Close() return nil, fmt.Errorf("ping sqlite database: %w", err) } return database, nil } func applyPragmas(ctx context.Context, database *sql.DB) error { pragmas := []string{ "PRAGMA foreign_keys = ON;", "PRAGMA journal_mode = WAL;", "PRAGMA busy_timeout = 5000;", "PRAGMA synchronous = NORMAL;", } for _, pragma := range pragmas { if _, err := database.ExecContext(ctx, pragma); err != nil { return fmt.Errorf("apply sqlite pragma %q: %w", pragma, err) } } return nil }