Unverified Commit 3ed66032 authored by Lemon-miaow's avatar Lemon-miaow
Browse files

feat(store): api/reaper/offsite/migrate 按版本集合校验 schema,库比二进制新时拒绝启动;bootstrap 迁移前失败回滚宿主二进制

parent b1678f78
Loading
Loading
Loading
Loading
+3 −2
Changes for cmd/felis/api.go: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import (
	"felis.lolicon.best/internal/reaper"
	"felis.lolicon.best/internal/registryprune"
	"felis.lolicon.best/internal/restore"
	"felis.lolicon.best/internal/store"
	"felis.lolicon.best/internal/submit"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -88,7 +87,9 @@ func cmdAPI(args []string, stdout, stderr io.Writer) int {

	ctx := ctrl.SetupSignalHandler()

	drv, err := store.Open(ctx, cfg.Database.URL)
	// Before anything serves: an api on a schema it was not built for answers with
	// errors, or writes rows the other version cannot read.
	drv, err := openStore(ctx, cfg.Database.URL, false)
	if err != nil {
		fmt.Fprintf(stderr, "felis api: open database: %v\n", err)
		return 1
+23 −0
Changes for cmd/felis/migrate.go: 23 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -111,3 +111,26 @@ func hasPending(done map[int]struct{}, migrations []store.Migration) bool {
	}
	return false
}

// openStore opens the business database for a command that reads and writes its
// tables, and refuses one whose schema this build was not written against: a newer
// Felis migrated it (a rolled-back binary), or, unless allowPending, migrations this
// build embeds have not run yet (a binary swapped in ahead of `felis migrate up`).
func openStore(ctx context.Context, url string, allowPending bool) (*store.PostgresDriver, error) {
	drv, err := store.Open(ctx, url)
	if err != nil {
		return nil, err
	}
	s, err := store.ReadSchema(ctx, drv)
	if err == nil {
		err = s.Err()
		if allowPending {
			err = s.Newer()
		}
	}
	if err != nil {
		drv.Close()
		return nil, err
	}
	return drv, nil
}
+2 −3
Changes for cmd/felis/offsite.go: 2 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@ import (
	"felis.lolicon.best/internal/dbbackup"
	"felis.lolicon.best/internal/offsite"
	"felis.lolicon.best/internal/platform"
	"felis.lolicon.best/internal/store"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -242,7 +241,7 @@ func runOffsiteSync(cfg *config.Config, env *offsiteEnv, archiveDir, backupPVC,
		}
		archiveDir = dir
	}
	drv, err := store.Open(ctx, cfg.Database.URL)
	drv, err := openStore(ctx, cfg.Database.URL, false)
	if err != nil {
		return offsite.Result{}, fmt.Errorf("open database: %w", err)
	}
@@ -536,7 +535,7 @@ func offsiteFetchWorlds(fs *flag.FlagSet, args []string, stdout, stderr io.Write
			return 1
		}
	}
	drv, err := store.Open(ctx, cfg.Database.URL)
	drv, err := openStore(ctx, cfg.Database.URL, false)
	if err != nil {
		fmt.Fprintf(stderr, "felis offsite fetch-worlds: open database: %v\n", err)
		return 1
+1 −2
Changes for cmd/felis/reaper.go: 1 added line, 2 removed lines.
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ import (
	"felis.lolicon.best/internal/mail"
	"felis.lolicon.best/internal/platform"
	"felis.lolicon.best/internal/reaper"
	"felis.lolicon.best/internal/store"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -71,7 +70,7 @@ func cmdReaper(args []string, stdout, stderr io.Writer) int {
		return 1
	}

	drv, err := store.Open(ctx, cfg.Database.URL)
	drv, err := openStore(ctx, cfg.Database.URL, false)
	if err != nil {
		fmt.Fprintf(stderr, "felis reaper: open database: %v\n", err)
		return 1
+3 −1
Changes for cmd/felis/setup.go: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -345,7 +345,9 @@ func openConfiguredSetup(ctx context.Context, cfgPath string) (*configuredSetup,
	if err != nil {
		return nil, &setupOpenError{stage: "load config", err: err}
	}
	drv, err := store.Open(ctx, cfg.Database.URL)
	// Pending migrations are the preflight's to apply; a newer schema is a rolled-back
	// binary, and nothing this console writes would match it.
	drv, err := openStore(ctx, cfg.Database.URL, true)
	if err != nil {
		return nil, &setupOpenError{stage: "open database", err: err}
	}
Loading