From 1bfe4f1d53876905e05173b58b955c551b60ebe0 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Fri, 6 Feb 2026 16:21:29 +0800 Subject: [PATCH] fix: Robust DB connection retries and move sandbox routes to admin group. --- api/admin_users_metrics.go | 4 ++++ api/api.go | 3 --- cmd/accountsvc/main.go | 49 ++++++++++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/api/admin_users_metrics.go b/api/admin_users_metrics.go index 1ac84c8..d242c26 100644 --- a/api/admin_users_metrics.go +++ b/api/admin_users_metrics.go @@ -175,4 +175,8 @@ func registerAdminRoutes(group *gin.RouterGroup, h *handler) { admin.GET("/blacklist", h.listBlacklist) admin.POST("/blacklist", h.addToBlacklist) admin.DELETE("/blacklist/:email", h.removeFromBlacklist) + + // Sandbox mode + admin.GET("/sandbox/binding", h.getSandboxBinding) + admin.POST("/sandbox/bind", h.bindSandboxNode) } diff --git a/api/api.go b/api/api.go index e4bc487..2eafdd0 100644 --- a/api/api.go +++ b/api/api.go @@ -308,9 +308,6 @@ func RegisterRoutes(r *gin.Engine, opts ...Option) { authProtected.POST("/admin/blacklist", h.addToBlacklist) authProtected.DELETE("/admin/blacklist/:email", h.removeFromBlacklist) - authProtected.GET("/admin/sandbox/binding", h.getSandboxBinding) - authProtected.POST("/admin/sandbox/bind", h.bindSandboxNode) - authProtected.GET("/users", h.listUsers) // Internal routes for service-to-service reads. diff --git a/cmd/accountsvc/main.go b/cmd/accountsvc/main.go index 71ab8b6..5eb8f40 100644 --- a/cmd/accountsvc/main.go +++ b/cmd/accountsvc/main.go @@ -642,9 +642,23 @@ func runServer(ctx context.Context, cfg *config.Config, logger *slog.Logger) err MaxIdleConns: cfg.Store.MaxIdleConns, } - st, cleanup, err := store.New(ctx, storeCfg) + // Initialize business store with retries to account for sidecar startup + var st store.Store + var cleanup func(context.Context) error + var err error + for i := 0; i < 15; i++ { + st, cleanup, err = store.New(ctx, storeCfg) + if err == nil { + break + } + if storeCfg.Driver == "" || storeCfg.Driver == "memory" { + return err + } + slog.Warn("retrying business store connection...", "attempt", i+1, "err", err) + time.Sleep(2 * time.Second) + } if err != nil { - return err + return fmt.Errorf("business store connection failed after sidecar wait: %w", err) } defer func() { if cleanup == nil { @@ -1355,19 +1369,30 @@ func openAdminSettingsDB(cfg config.Store) (*gorm.DB, func(context.Context) erro db *gorm.DB err error ) - switch driver { - case "", "memory": - db, err = gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) - case "postgres", "postgresql", "pgx": - if strings.TrimSpace(cfg.DSN) == "" { - return nil, nil, errors.New("admin settings database requires a dsn") + for i := 0; i < 15; i++ { + switch driver { + case "", "memory": + db, err = gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) + case "postgres", "postgresql", "pgx": + if strings.TrimSpace(cfg.DSN) == "" { + return nil, nil, errors.New("admin settings database requires a dsn") + } + db, err = gorm.Open(postgres.Open(cfg.DSN), &gorm.Config{}) + default: + return nil, nil, fmt.Errorf("unsupported admin settings driver %q", cfg.Driver) } - db, err = gorm.Open(postgres.Open(cfg.DSN), &gorm.Config{}) - default: - return nil, nil, fmt.Errorf("unsupported admin settings driver %q", cfg.Driver) + + if err == nil { + break + } + if driver == "" || driver == "memory" { + return nil, nil, err + } + slog.Warn("retrying admin settings db connection...", "attempt", i+1, "err", err) + time.Sleep(2 * time.Second) } if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("admin settings db connection failed after sidecar wait: %w", err) } if err := db.AutoMigrate(&model.AdminSetting{}, &model.SandboxBinding{}); err != nil {