* feat(unified): migration at startup based on resource count -- draft * feat: introduce auto migration enablement for dashboards & folders * feat: enable auto migration based on threshold * fix: improve * fix: pass in the auto migrate per migration definition * fix: minor * fix: only use one options * fix: test * fix: test * fix: tests * fix: simplify configs * chore: rename * fix: add integration test * fix: add integration test * fix: integration tests * chore: add comments * fix: address comment * fix: address comments * fix: test and auto migration flow * fix: test --------- Co-authored-by: Rafael Paulovic <rafael.paulovic@grafana.com>
105 lines
3.1 KiB
Go
105 lines
3.1 KiB
Go
package migrations
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
"github.com/grafana/grafana/pkg/infra/kvstore"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/infra/metrics"
|
|
sqlstoremigrator "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/grafana/grafana/pkg/storage/unified/migrations/contract"
|
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"go.opentelemetry.io/otel"
|
|
)
|
|
|
|
var tracer = otel.Tracer("github.com/grafana/grafana/pkg/storage/unified/migrations")
|
|
var logger = log.New("storage.unified.migrations")
|
|
|
|
type UnifiedStorageMigrationServiceImpl struct {
|
|
migrator UnifiedMigrator
|
|
cfg *setting.Cfg
|
|
sqlStore db.DB
|
|
kv kvstore.KVStore
|
|
client resource.ResourceClient
|
|
}
|
|
|
|
var _ contract.UnifiedStorageMigrationService = (*UnifiedStorageMigrationServiceImpl)(nil)
|
|
|
|
// ProvideUnifiedStorageMigrationService is a Wire provider that creates the migration service.
|
|
func ProvideUnifiedStorageMigrationService(
|
|
migrator UnifiedMigrator,
|
|
cfg *setting.Cfg,
|
|
sqlStore db.DB,
|
|
kv kvstore.KVStore,
|
|
client resource.ResourceClient,
|
|
) contract.UnifiedStorageMigrationService {
|
|
return &UnifiedStorageMigrationServiceImpl{
|
|
migrator: migrator,
|
|
cfg: cfg,
|
|
sqlStore: sqlStore,
|
|
kv: kv,
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
func (p *UnifiedStorageMigrationServiceImpl) Run(ctx context.Context) error {
|
|
// skip migrations if disabled in config
|
|
if p.cfg.DisableDataMigrations {
|
|
metrics.MUnifiedStorageMigrationStatus.Set(1)
|
|
logger.Info("Data migrations are disabled, skipping")
|
|
return nil
|
|
}
|
|
|
|
logger.Info("Running migrations for unified storage")
|
|
metrics.MUnifiedStorageMigrationStatus.Set(3)
|
|
return RegisterMigrations(ctx, p.migrator, p.cfg, p.sqlStore, p.client)
|
|
}
|
|
|
|
func RegisterMigrations(
|
|
ctx context.Context,
|
|
migrator UnifiedMigrator,
|
|
cfg *setting.Cfg,
|
|
sqlStore db.DB,
|
|
client resource.ResourceClient,
|
|
) error {
|
|
ctx, span := tracer.Start(ctx, "storage.unified.RegisterMigrations")
|
|
defer span.End()
|
|
mg := sqlstoremigrator.NewScopedMigrator(sqlStore.GetEngine(), cfg, "unifiedstorage")
|
|
mg.AddCreateMigration()
|
|
|
|
if err := prometheus.Register(mg); err != nil {
|
|
logger.Warn("Failed to register migrator metrics", "error", err)
|
|
}
|
|
|
|
if err := validateRegisteredResources(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := registerMigrations(ctx, cfg, mg, migrator, client, sqlStore); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Run all registered migrations (blocking)
|
|
sec := cfg.Raw.Section("database")
|
|
db := mg.DBEngine.DB().DB
|
|
maxOpenConns := db.Stats().MaxOpenConnections
|
|
if maxOpenConns <= 2 {
|
|
// migrations require at least 3 connections due to extra GRPC connections
|
|
db.SetMaxOpenConns(3)
|
|
defer db.SetMaxOpenConns(maxOpenConns)
|
|
}
|
|
err := mg.RunMigrations(ctx,
|
|
sec.Key("migration_locking").MustBool(true),
|
|
sec.Key("locking_attempt_timeout_sec").MustInt())
|
|
if err != nil {
|
|
return fmt.Errorf("unified storage data migration failed: %w", err)
|
|
}
|
|
|
|
logger.Info("Unified storage migrations completed successfully")
|
|
return nil
|
|
}
|