diff --git a/qan-api2/db.go b/qan-api2/db.go index 022f7982ada..31797ee321b 100644 --- a/qan-api2/db.go +++ b/qan-api2/db.go @@ -17,6 +17,7 @@ package main import ( "embed" + "errors" "fmt" "log" "net/url" @@ -28,7 +29,6 @@ import ( "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/jmoiron/sqlx" // TODO: research alternatives. Ex.: https://github.com/go-reform/reform "github.com/jmoiron/sqlx/reflectx" - "github.com/pkg/errors" ) const ( @@ -113,9 +113,32 @@ func runMigrations(dsn string) error { // run up to the latest migration err = m.Up() - if errors.Is(err, migrate.ErrNoChange) { + if err == nil || errors.Is(err, migrate.ErrNoChange) { return nil } + + // If the database is in dirty state, try to fix it (PMM-14305) + var errDirty migrate.ErrDirty + if errors.As(err, &errDirty) { + log.Printf("Migration %d was unsuccessful, trying to fix it...", errDirty.Version) + + ver := errDirty.Version - 1 + if ver == 0 { + // Note: since 0th migration does not exist, we set it to -1, which means "start from scratch" + ver = -1 + } + err = m.Force(ver) + if err != nil { + return fmt.Errorf("can't force the migration %d: %w", ver, err) + } + + // try to run migrations again, starting from the forced version + err = m.Up() + if errors.Is(err, migrate.ErrNoChange) { + return nil + } + } + return err } diff --git a/qan-api2/main.go b/qan-api2/main.go index bd504387677..c258729c3e9 100644 --- a/qan-api2/main.go +++ b/qan-api2/main.go @@ -18,6 +18,7 @@ package main import ( "bytes" "context" + "errors" _ "expvar" // register /debug/vars "fmt" "html/template" @@ -38,7 +39,6 @@ import ( grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" grpc_gateway "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/jmoiron/sqlx" - "github.com/pkg/errors" prom "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" diff --git a/qan-api2/utils/logger/logger.go b/qan-api2/utils/logger/logger.go index f9d2b2b5ce4..90aafd631d0 100644 --- a/qan-api2/utils/logger/logger.go +++ b/qan-api2/utils/logger/logger.go @@ -28,7 +28,7 @@ type keyStruct struct{} var key = keyStruct{} -// Get returns logrus entry for given context. Set must be called before this method is called. +// Get returns logrus entry for given context. SetEntry must be called before this method is called. func Get(ctx context.Context) *logrus.Entry { v := ctx.Value(key) if v == nil { @@ -37,11 +37,6 @@ func Get(ctx context.Context) *logrus.Entry { return v.(*logrus.Entry) //nolint:forcetypeassert } -// Set returns derived context with set logrus entry with given request ID. -func Set(ctx context.Context, requestID string) context.Context { - return SetEntry(ctx, logrus.WithField("request", requestID)) -} - // SetEntry returns derived context with set given logrus entry. func SetEntry(ctx context.Context, l *logrus.Entry) context.Context { if ctx.Value(key) != nil {