Add SQLite store and embedded migration runner
CI / ci (pull_request) Successful in 56s
CI / ci (push) Successful in 49s
Independent review Not signed off — 0 high, 1 medium (#10)

internal/store opens $MEALQUEST_DATA_DIR/mealquest.db with modernc.org/sqlite
(CGO-free) as one writer connection and a read-only pool of four, with
busy_timeout=5000, journal_mode=WAL and foreign_keys=ON on every connection.

migrations/*.sql are embedded and applied at boot in filename order, each
in its own transaction together with its schema_migrations row, so a failing
migration rolls back and fails boot. A database holding a version this build
does not know is refused. 0001_init.sql is a placeholder until the v1 schema
lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 00:47:33 -04:00
co-authored by Claude Opus 5.5
parent 65b27a7689
commit c777668ef5
9 changed files with 573 additions and 2 deletions
+15
View File
@@ -15,6 +15,8 @@ import (
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/config"
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/frontend"
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/server"
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/store"
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/migrations"
)
// version is set at build time with -ldflags "-X main.version=<version>".
@@ -38,6 +40,19 @@ func run(cfg config.Config, logger *slog.Logger) error {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
db, err := store.Open(ctx, cfg.DataDir)
if err != nil {
return err
}
defer func() {
if err := db.Close(); err != nil {
logger.Error("close database", "error", err)
}
}()
if err := store.Migrate(ctx, db.Writer, migrations.FS); err != nil {
return err
}
router, err := server.NewRouter(logger, version, frontend.Assets())
if err != nil {
return err