mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-29 22:47:14 +00:00
perf(settings): save all settings in one transaction
UpdateAllSetting issued a separate SELECT plus Save per field in its own autocommit transaction, so each panel-settings save triggered 100+ SQLite write transactions (one fsync each). Wrap the whole update in a single transaction, read existing rows once, and skip unchanged values.
This commit is contained in:
@@ -23,6 +23,8 @@ import (
|
|||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/reflect_util"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/reflect_util"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed config.json
|
//go:embed config.json
|
||||||
@@ -1049,17 +1051,37 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
|||||||
v := reflect.ValueOf(allSetting).Elem()
|
v := reflect.ValueOf(allSetting).Elem()
|
||||||
t := reflect.TypeFor[entity.AllSetting]()
|
t := reflect.TypeFor[entity.AllSetting]()
|
||||||
fields := reflect_util.GetFields(t)
|
fields := reflect_util.GetFields(t)
|
||||||
errs := make([]error, 0)
|
|
||||||
for _, field := range fields {
|
db := database.GetDB()
|
||||||
key := field.Tag.Get("json")
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
fieldV := v.FieldByName(field.Name)
|
var existing []*model.Setting
|
||||||
value := fmt.Sprint(fieldV.Interface())
|
if err := tx.Find(&existing).Error; err != nil {
|
||||||
err := s.saveSetting(key, value)
|
return err
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
}
|
||||||
}
|
byKey := make(map[string]*model.Setting, len(existing))
|
||||||
return common.Combine(errs...)
|
for _, st := range existing {
|
||||||
|
byKey[st.Key] = st
|
||||||
|
}
|
||||||
|
for _, field := range fields {
|
||||||
|
key := field.Tag.Get("json")
|
||||||
|
fieldV := v.FieldByName(field.Name)
|
||||||
|
value := fmt.Sprint(fieldV.Interface())
|
||||||
|
if st, ok := byKey[key]; ok {
|
||||||
|
if st.Value == value {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
st.Value = value
|
||||||
|
if err := tx.Save(st).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := tx.Create(&model.Setting{Key: key, Value: value}).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SettingService) preserveRedactedSecrets(allSetting *entity.AllSetting) error {
|
func (s *SettingService) preserveRedactedSecrets(allSetting *entity.AllSetting) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user