package db import ( "context" "database/sql" "fmt" "log/slog" "path/filepath" "github.com/ncruces/go-sqlite3" "github.com/ncruces/go-sqlite3/driver" _ "github.com/ncruces/go-sqlite3/embed" "github.com/pressly/goose/v3" ) func Connect(ctx context.Context, dataDir string) (*sql.DB, error) { if dataDir == "" { return nil, fmt.Errorf("data.dir is not set") } dbPath := filepath.Join(dataDir, "crush.db") // Set pragmas for better performance pragmas := []string{ "PRAGMA foreign_keys = ON;", "PRAGMA journal_mode = WAL;", "PRAGMA page_size = 4096;", "PRAGMA cache_size = -8000;", "PRAGMA synchronous = NORMAL;", "PRAGMA secure_delete = ON;", } db, err := driver.Open(dbPath, func(c *sqlite3.Conn) error { for _, pragma := range pragmas { if err := c.Exec(pragma); err != nil { return fmt.Errorf("failed to set pragma `%s`: %w", pragma, err) } } return nil }) if err != nil { return nil, fmt.Errorf("failed to open database: %w", err) } // Verify connection if err = db.PingContext(ctx); err != nil { db.Close() return nil, fmt.Errorf("failed to connect to database: %w", err) } goose.SetBaseFS(FS) if err := goose.SetDialect("sqlite3"); err != nil { slog.Error("Failed to set dialect", "error", err) return nil, fmt.Errorf("failed to set dialect: %w", err) } if err := goose.Up(db, "migrations"); err != nil { slog.Error("Failed to apply migrations", "error", err) return nil, fmt.Errorf("failed to apply migrations: %w", err) } return db, nil }