connect.go

 1package db
 2
 3import (
 4	"context"
 5	"database/sql"
 6	"embed"
 7	"fmt"
 8	"log/slog"
 9	"path/filepath"
10	"testing"
11
12	"github.com/pressly/goose/v3"
13)
14
15var pragmas = map[string]string{
16	"foreign_keys":  "ON",
17	"journal_mode":  "WAL",
18	"page_size":     "4096",
19	"cache_size":    "-8000",
20	"synchronous":   "NORMAL",
21	"secure_delete": "ON",
22	"busy_timeout":  "30000",
23}
24
25//go:embed migrations/*.sql
26var FS embed.FS
27
28func init() {
29	goose.SetBaseFS(FS)
30
31	if testing.Testing() {
32		goose.SetLogger(goose.NopLogger())
33	}
34
35}
36
37// Connect opens a SQLite database connection and runs migrations.
38func Connect(ctx context.Context, dataDir string) (*sql.DB, error) {
39	if dataDir == "" {
40		return nil, fmt.Errorf("data.dir is not set")
41	}
42	dbPath := filepath.Join(dataDir, "crush.db")
43
44	db, err := openDB(dbPath)
45	if err != nil {
46		return nil, err
47	}
48
49	if err = db.PingContext(ctx); err != nil {
50		db.Close()
51		return nil, fmt.Errorf("failed to connect to database: %w", err)
52	}
53
54	if err := goose.SetDialect("sqlite3"); err != nil {
55		slog.Error("Failed to set dialect", "error", err)
56		return nil, fmt.Errorf("failed to set dialect: %w", err)
57	}
58
59	if err := goose.Up(db, "migrations"); err != nil {
60		slog.Error("Failed to apply migrations", "error", err)
61		return nil, fmt.Errorf("failed to apply migrations: %w", err)
62	}
63
64	return db, nil
65}