backend barebone done, big chunk of work done
CI / Go (build + vet + test) (push) Canceled after 0s
CI / Web (build + lint) (push) Canceled after 0s

This commit is contained in:
vantablackTea
2026-09-27 19:42:49 +03:00
parent 1a669c948a
commit c79a3cfe68
36 changed files with 2607 additions and 17 deletions
+89
View File
@@ -0,0 +1,89 @@
package store
import (
"context"
"embed"
"sort"
"strconv"
"strings"
)
//go:embed migrations/*.sql
var migrationFiles embed.FS
// Migrate applies any pending SQL migrations in order within a single transaction.
func (s *Store) Migrate(ctx context.Context) error {
conn, err := s.pool.Acquire(ctx)
if err != nil {
return err
}
defer conn.Release()
tx, err := conn.Begin(ctx)
if err != nil {
return err
}
defer func() {
if tx != nil {
tx.Rollback(ctx)
}
}()
_, err = tx.Exec(ctx, `CREATE TABLE IF NOT EXISTS schema_migrations (
version INT PRIMARY KEY
)`)
if err != nil {
return err
}
entries, err := migrationFiles.ReadDir("migrations")
if err != nil {
return err
}
type mig struct {
ver int
name string
}
var migs []mig
for _, e := range entries {
name := e.Name()
if !strings.HasSuffix(name, ".sql") {
continue
}
parts := strings.SplitN(name, "_", 2)
v, err := strconv.Atoi(parts[0])
if err != nil {
continue
}
migs = append(migs, mig{ver: v, name: name})
}
sort.Slice(migs, func(i, j int) bool { return migs[i].ver < migs[j].ver })
for _, m := range migs {
var exists bool
err = tx.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM schema_migrations WHERE version=$1)", m.ver).Scan(&exists)
if err != nil {
return err
}
if exists {
continue
}
data, err := migrationFiles.ReadFile("migrations/" + m.name)
if err != nil {
return err
}
if _, err = tx.Exec(ctx, string(data)); err != nil {
return err
}
if _, err = tx.Exec(ctx, "INSERT INTO schema_migrations(version) VALUES($1)", m.ver); err != nil {
return err
}
}
if err = tx.Commit(ctx); err != nil {
return err
}
tx = nil
return nil
}