refactor: usar sqlite_apply_migrations_go_infra del registry
Sustituye applyMigrations + splitSQLStatements + isIdempotentError locales por infra.ApplyMigrations del registry. ~55 LOC eliminadas. - store.go: import fn-registry/functions/infra, llama infra.ApplyMigrations - go.mod: declara dep fn-registry con replace local - app.md: declara sqlite_apply_migrations_go_infra en uses_functions Sin cambio funcional (mismo parser naive de `;`, mismas reglas idempotentes). Bug fixes futuros se aplicaran automaticamente al consumir registry.
This commit is contained in:
@@ -5,11 +5,10 @@ import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fn-registry/functions/infra"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
@@ -69,61 +68,7 @@ func (s *Store) Close() error {
|
||||
}
|
||||
|
||||
func (s *Store) migrate() error {
|
||||
files, err := fs.Glob(migrationsFS, "migrations/*.sql")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(files)
|
||||
for _, f := range files {
|
||||
b, err := migrationsFS.ReadFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Split por sentencia para que cada ALTER pueda fallar idempotentemente
|
||||
// sin abortar el resto. SQLite acepta multiples sentencias en Exec(),
|
||||
// pero no ignora duplicados — ejecutamos una a una.
|
||||
stmts := splitSQLStatements(string(b))
|
||||
for _, stmt := range stmts {
|
||||
s2 := strings.TrimSpace(stmt)
|
||||
if s2 == "" {
|
||||
continue
|
||||
}
|
||||
if _, err := s.db.Exec(s2); err != nil {
|
||||
if isIdempotentError(err) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("migrate %s: %w", f, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func splitSQLStatements(s string) []string {
|
||||
out := []string{}
|
||||
cur := strings.Builder{}
|
||||
for _, line := range strings.Split(s, "\n") {
|
||||
trim := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(trim, "--") || trim == "" {
|
||||
continue
|
||||
}
|
||||
cur.WriteString(line)
|
||||
cur.WriteString("\n")
|
||||
if strings.HasSuffix(trim, ";") {
|
||||
out = append(out, cur.String())
|
||||
cur.Reset()
|
||||
}
|
||||
}
|
||||
if cur.Len() > 0 {
|
||||
out = append(out, cur.String())
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func isIdempotentError(err error) bool {
|
||||
msg := err.Error()
|
||||
return strings.Contains(msg, "duplicate column") ||
|
||||
strings.Contains(msg, "already exists")
|
||||
return infra.ApplyMigrations(s.db, migrationsFS, "migrations/*.sql")
|
||||
}
|
||||
|
||||
func (s *Store) AddTarget(t DeployTarget) error {
|
||||
|
||||
Reference in New Issue
Block a user