From e96277ee8559b62fd8b8ef630134d63f417d1bb4 Mon Sep 17 00:00:00 2001 From: veypi Date: Mon, 16 Feb 2026 04:53:52 +0800 Subject: [PATCH] fix(api/settings): wrap batch update in database transaction Use database transaction for batch settings update to ensure atomicity. If any individual update fails, the entire batch will be rolled back, preventing partial configuration updates. - Wrap all updates in db.Transaction() - Return detailed error on failure --- api/settings/update.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/api/settings/update.go b/api/settings/update.go index ac86cf8..8c4edd9 100644 --- a/api/settings/update.go +++ b/api/settings/update.go @@ -8,8 +8,10 @@ package settings import ( "github.com/veypi/vbase/auth" + "github.com/veypi/vbase/cfg" "github.com/veypi/vbase/models" "github.com/veypi/vigo" + "gorm.io/gorm" ) // UpdateItem 更新项 @@ -45,12 +47,28 @@ func update(x *vigo.X, req *UpdateRequest) (*UpdateResponse, error) { return nil, vigo.ErrForbidden.WithString("only admin can update settings") } + // 使用事务确保批量更新的原子性 + db := cfg.DB() updated := 0 - for _, item := range req.Settings { - if err := models.SetSetting(item.Key, item.Value, userID); err != nil { - return nil, vigo.ErrInternalServer.WithString("failed to update " + item.Key) + + err = db.Transaction(func(tx *gorm.DB) error { + for _, item := range req.Settings { + var s models.Setting + if err := tx.Where("`key` = ?", item.Key).First(&s).Error; err != nil { + return err + } + s.Value = item.Value + s.UpdatedBy = userID + if err := tx.Save(&s).Error; err != nil { + return err + } + updated++ } - updated++ + return nil + }) + + if err != nil { + return nil, vigo.ErrInternalServer.WithError(err) } return &UpdateResponse{