perf: Speed ​​of database initialization (#7694)

* perf: 优化非sqlite3数据库时初始化慢的问题

* refactor
pull/7673/head
j2rong4cn 2024-12-25 21:08:22 +08:00 committed by GitHub
parent b8bd14f99b
commit db99224126
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 36 deletions

View File

@ -3,6 +3,7 @@ package data
import ( import (
"github.com/alist-org/alist/v3/cmd/flags" "github.com/alist-org/alist/v3/cmd/flags"
"github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/offline_download/tool" "github.com/alist-org/alist/v3/internal/offline_download/tool"
"github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/op"
@ -21,17 +22,19 @@ func initSettings() {
if err != nil { if err != nil {
utils.Log.Fatalf("failed get settings: %+v", err) utils.Log.Fatalf("failed get settings: %+v", err)
} }
for i := range settings { settingMap := map[string]*model.SettingItem{}
if !isActive(settings[i].Key) && settings[i].Flag != model.DEPRECATED { for _, v := range settings {
settings[i].Flag = model.DEPRECATED if !isActive(v.Key) && v.Flag != model.DEPRECATED {
err = op.SaveSettingItem(&settings[i]) v.Flag = model.DEPRECATED
err = op.SaveSettingItem(&v)
if err != nil { if err != nil {
utils.Log.Fatalf("failed save setting: %+v", err) utils.Log.Fatalf("failed save setting: %+v", err)
} }
} }
settingMap[v.Key] = &v
} }
// create or save setting // create or save setting
save := false
for i := range initialSettingItems { for i := range initialSettingItems {
item := &initialSettingItems[i] item := &initialSettingItems[i]
item.Index = uint(i) item.Index = uint(i)
@ -39,26 +42,33 @@ func initSettings() {
item.PreDefault = item.Value item.PreDefault = item.Value
} }
// err // err
stored, err := op.GetSettingItemByKey(item.Key) stored, ok := settingMap[item.Key]
if !ok {
stored, err = op.GetSettingItemByKey(item.Key)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
utils.Log.Fatalf("failed get setting: %+v", err) utils.Log.Fatalf("failed get setting: %+v", err)
continue continue
} }
// save }
if stored != nil && item.Key != conf.VERSION && stored.Value != item.PreDefault { if stored != nil && item.Key != conf.VERSION && stored.Value != item.PreDefault {
item.Value = stored.Value item.Value = stored.Value
} }
if stored == nil || *item != *stored {
err = op.SaveSettingItem(item)
if err != nil {
utils.Log.Fatalf("failed save setting: %+v", err)
}
} else {
// Not save so needs to execute hook
_, err = op.HandleSettingItemHook(item) _, err = op.HandleSettingItemHook(item)
if err != nil { if err != nil {
utils.Log.Errorf("failed to execute hook on %s: %+v", item.Key, err) utils.Log.Errorf("failed to execute hook on %s: %+v", item.Key, err)
continue
} }
// save
if stored == nil || *item != *stored {
save = true
}
}
if save {
err = db.SaveSettingItems(initialSettingItems)
if err != nil {
utils.Log.Fatalf("failed save setting: %+v", err)
} else {
op.SettingCacheUpdate()
} }
} }
} }

View File

@ -56,20 +56,20 @@ func InitDB() {
} }
case "mysql": case "mysql":
{ {
dsn := database.DSN
if dsn == "" {
//[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN] //[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s", dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s",
database.User, database.Password, database.Host, database.Port, database.Name, database.SSLMode) database.User, database.Password, database.Host, database.Port, database.Name, database.SSLMode)
if database.DSN != "" {
dsn = database.DSN
} }
dB, err = gorm.Open(mysql.Open(dsn), gormConfig) dB, err = gorm.Open(mysql.Open(dsn), gormConfig)
} }
case "postgres": case "postgres":
{ {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=Asia/Shanghai", dsn := database.DSN
if dsn == "" {
dsn = fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=Asia/Shanghai",
database.Host, database.User, database.Password, database.Name, database.Port, database.SSLMode) database.Host, database.User, database.Password, database.Name, database.Port, database.SSLMode)
if database.DSN != "" {
dsn = database.DSN
} }
dB, err = gorm.Open(postgres.Open(dsn), gormConfig) dB, err = gorm.Open(postgres.Open(dsn), gormConfig)
} }

View File

@ -26,7 +26,7 @@ var settingGroupCacheF = func(key string, item []model.SettingItem) {
settingGroupCache.Set(key, item, cache.WithEx[[]model.SettingItem](time.Hour)) settingGroupCache.Set(key, item, cache.WithEx[[]model.SettingItem](time.Hour))
} }
func settingCacheUpdate() { func SettingCacheUpdate() {
settingCache.Clear() settingCache.Clear()
settingGroupCache.Clear() settingGroupCache.Clear()
} }
@ -167,7 +167,7 @@ func SaveSettingItems(items []model.SettingItem) error {
} }
} }
if len(errs) < len(items)-len(noHookItems)+1 { if len(errs) < len(items)-len(noHookItems)+1 {
settingCacheUpdate() SettingCacheUpdate()
} }
return utils.MergeErrors(errs...) return utils.MergeErrors(errs...)
} }
@ -181,7 +181,7 @@ func SaveSettingItem(item *model.SettingItem) (err error) {
if err = db.SaveSettingItem(item); err != nil { if err = db.SaveSettingItem(item); err != nil {
return err return err
} }
settingCacheUpdate() SettingCacheUpdate()
return nil return nil
} }
@ -193,6 +193,6 @@ func DeleteSettingItemByKey(key string) error {
if !old.IsDeprecated() { if !old.IsDeprecated() {
return errors.Errorf("setting [%s] is not deprecated", key) return errors.Errorf("setting [%s] is not deprecated", key)
} }
settingCacheUpdate() SettingCacheUpdate()
return db.DeleteSettingItemByKey(key) return db.DeleteSettingItemByKey(key)
} }

View File

@ -12,16 +12,16 @@ import (
func GetApiUrl(r *http.Request) string { func GetApiUrl(r *http.Request) string {
api := conf.Conf.SiteURL api := conf.Conf.SiteURL
if strings.HasPrefix(api, "http") { if strings.HasPrefix(api, "http") {
return api return strings.TrimSuffix(api, "/")
} }
if r != nil { if r != nil {
protocol := "http" protocol := "http"
if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" { if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" {
protocol = "https" protocol = "https"
} }
host := r.Host host := r.Header.Get("X-Forwarded-Host")
if r.Header.Get("X-Forwarded-Host") != "" { if host == "" {
host = r.Header.Get("X-Forwarded-Host") host = r.Host
} }
api = fmt.Sprintf("%s://%s", protocol, stdpath.Join(host, api)) api = fmt.Sprintf("%s://%s", protocol, stdpath.Join(host, api))
} }