From 902943f167ca098448b503bb9fd0d51196c2df45 Mon Sep 17 00:00:00 2001 From: mlsmaycon Date: Sat, 12 Sep 2026 12:36:21 +0000 Subject: [PATCH] [management] Close the cloned test store when seeding it fails The Postgres and MySQL test constructors opened the store and then returned an error from SaveInstallationID or SaveAccount without closing it, leaking the connection and the pgx pool. Both now share one seeding helper and release the store on that path. --- management/server/store/sql_store.go | 45 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/management/server/store/sql_store.go b/management/server/store/sql_store.go index 5f77a4259..593199b0f 100644 --- a/management/server/store/sql_store.go +++ b/management/server/store/sql_store.go @@ -3222,18 +3222,11 @@ func newPostgresqlStoreFromSqlStore(ctx context.Context, sqliteStore *SqlStore, return nil, err } - err = store.SaveInstallationID(ctx, sqliteStore.GetInstallationID()) - if err != nil { + if err := seedFromSqliteStore(ctx, store, sqliteStore); err != nil { + closeStore(ctx, store) return nil, err } - for _, account := range sqliteStore.GetAllAccounts(ctx) { - err := store.SaveAccount(ctx, account) - if err != nil { - return nil, err - } - } - return store, nil } @@ -3286,24 +3279,40 @@ func NewMysqlStoreFromSqlStore(ctx context.Context, sqliteStore *SqlStore, dsn s return newMysqlStoreFromSqlStore(ctx, sqliteStore, dsn, metrics, false) } +// seedFromSqliteStore copies the installation ID and the accounts of the +// sqlite seed store into a freshly created engine store. +func seedFromSqliteStore(ctx context.Context, store, sqliteStore *SqlStore) error { + if err := store.SaveInstallationID(ctx, sqliteStore.GetInstallationID()); err != nil { + return err + } + for _, account := range sqliteStore.GetAllAccounts(ctx) { + if err := store.SaveAccount(ctx, account); err != nil { + return err + } + } + return nil +} + +// closeStore releases a store that is not handed to the caller, so a failed +// seed does not leak its connection and pool. +func closeStore(ctx context.Context, store *SqlStore) { + store.Close(ctx) + if store.pool != nil { + store.pool.Close() + } +} + func newMysqlStoreFromSqlStore(ctx context.Context, sqliteStore *SqlStore, dsn string, metrics telemetry.AppMetrics, skipMigration bool) (*SqlStore, error) { store, err := NewMysqlStore(ctx, dsn, metrics, skipMigration) if err != nil { return nil, err } - err = store.SaveInstallationID(ctx, sqliteStore.GetInstallationID()) - if err != nil { + if err := seedFromSqliteStore(ctx, store, sqliteStore); err != nil { + closeStore(ctx, store) return nil, err } - for _, account := range sqliteStore.GetAllAccounts(ctx) { - err := store.SaveAccount(ctx, account) - if err != nil { - return nil, err - } - } - return store, nil }