|
package op |
|
|
|
import ( |
|
"sort" |
|
"strconv" |
|
"strings" |
|
"time" |
|
|
|
"github.com/Xhofe/go-cache" |
|
"github.com/alist-org/alist/v3/internal/db" |
|
"github.com/alist-org/alist/v3/internal/model" |
|
"github.com/alist-org/alist/v3/pkg/singleflight" |
|
"github.com/alist-org/alist/v3/pkg/utils" |
|
"github.com/pkg/errors" |
|
) |
|
|
|
var settingCache = cache.NewMemCache(cache.WithShards[*model.SettingItem](4)) |
|
var settingG singleflight.Group[*model.SettingItem] |
|
var settingCacheF = func(item *model.SettingItem) { |
|
settingCache.Set(item.Key, item, cache.WithEx[*model.SettingItem](time.Hour)) |
|
} |
|
|
|
var settingGroupCache = cache.NewMemCache(cache.WithShards[[]model.SettingItem](4)) |
|
var settingGroupG singleflight.Group[[]model.SettingItem] |
|
var settingGroupCacheF = func(key string, item []model.SettingItem) { |
|
settingGroupCache.Set(key, item, cache.WithEx[[]model.SettingItem](time.Hour)) |
|
} |
|
|
|
func settingCacheUpdate() { |
|
settingCache.Clear() |
|
settingGroupCache.Clear() |
|
} |
|
|
|
func GetPublicSettingsMap() map[string]string { |
|
items, _ := GetPublicSettingItems() |
|
pSettings := make(map[string]string) |
|
for _, item := range items { |
|
pSettings[item.Key] = item.Value |
|
} |
|
return pSettings |
|
} |
|
|
|
func GetSettingsMap() map[string]string { |
|
items, _ := GetSettingItems() |
|
settings := make(map[string]string) |
|
for _, item := range items { |
|
settings[item.Key] = item.Value |
|
} |
|
return settings |
|
} |
|
|
|
func GetSettingItems() ([]model.SettingItem, error) { |
|
if items, ok := settingGroupCache.Get("ALL_SETTING_ITEMS"); ok { |
|
return items, nil |
|
} |
|
items, err, _ := settingGroupG.Do("ALL_SETTING_ITEMS", func() ([]model.SettingItem, error) { |
|
_items, err := db.GetSettingItems() |
|
if err != nil { |
|
return nil, err |
|
} |
|
settingGroupCacheF("ALL_SETTING_ITEMS", _items) |
|
return _items, nil |
|
}) |
|
return items, err |
|
} |
|
|
|
func GetPublicSettingItems() ([]model.SettingItem, error) { |
|
if items, ok := settingGroupCache.Get("ALL_PUBLIC_SETTING_ITEMS"); ok { |
|
return items, nil |
|
} |
|
items, err, _ := settingGroupG.Do("ALL_PUBLIC_SETTING_ITEMS", func() ([]model.SettingItem, error) { |
|
_items, err := db.GetPublicSettingItems() |
|
if err != nil { |
|
return nil, err |
|
} |
|
settingGroupCacheF("ALL_PUBLIC_SETTING_ITEMS", _items) |
|
return _items, nil |
|
}) |
|
return items, err |
|
} |
|
|
|
func GetSettingItemByKey(key string) (*model.SettingItem, error) { |
|
if item, ok := settingCache.Get(key); ok { |
|
return item, nil |
|
} |
|
|
|
item, err, _ := settingG.Do(key, func() (*model.SettingItem, error) { |
|
_item, err := db.GetSettingItemByKey(key) |
|
if err != nil { |
|
return nil, err |
|
} |
|
settingCacheF(_item) |
|
return _item, nil |
|
}) |
|
return item, err |
|
} |
|
|
|
func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) { |
|
var items []model.SettingItem |
|
for _, key := range keys { |
|
item, err := GetSettingItemByKey(key) |
|
if err != nil { |
|
return nil, err |
|
} |
|
items = append(items, *item) |
|
} |
|
return items, nil |
|
} |
|
|
|
func GetSettingItemsByGroup(group int) ([]model.SettingItem, error) { |
|
key := strconv.Itoa(group) |
|
if items, ok := settingGroupCache.Get(key); ok { |
|
return items, nil |
|
} |
|
items, err, _ := settingGroupG.Do(key, func() ([]model.SettingItem, error) { |
|
_items, err := db.GetSettingItemsByGroup(group) |
|
if err != nil { |
|
return nil, err |
|
} |
|
settingGroupCacheF(key, _items) |
|
return _items, nil |
|
}) |
|
return items, err |
|
} |
|
|
|
func GetSettingItemsInGroups(groups []int) ([]model.SettingItem, error) { |
|
sort.Ints(groups) |
|
key := strings.Join(utils.MustSliceConvert(groups, func(i int) string { |
|
return strconv.Itoa(i) |
|
}), ",") |
|
|
|
if items, ok := settingGroupCache.Get(key); ok { |
|
return items, nil |
|
} |
|
items, err, _ := settingGroupG.Do(key, func() ([]model.SettingItem, error) { |
|
_items, err := db.GetSettingItemsInGroups(groups) |
|
if err != nil { |
|
return nil, err |
|
} |
|
settingGroupCacheF(key, _items) |
|
return _items, nil |
|
}) |
|
return items, err |
|
} |
|
|
|
func SaveSettingItems(items []model.SettingItem) error { |
|
noHookItems := make([]model.SettingItem, 0) |
|
errs := make([]error, 0) |
|
for i := range items { |
|
if ok, err := HandleSettingItemHook(&items[i]); ok { |
|
if err != nil { |
|
errs = append(errs, err) |
|
} else { |
|
err = db.SaveSettingItem(&items[i]) |
|
if err != nil { |
|
errs = append(errs, err) |
|
} |
|
} |
|
} else { |
|
noHookItems = append(noHookItems, items[i]) |
|
} |
|
} |
|
if len(noHookItems) > 0 { |
|
err := db.SaveSettingItems(noHookItems) |
|
if err != nil { |
|
errs = append(errs, err) |
|
} |
|
} |
|
if len(errs) < len(items)-len(noHookItems)+1 { |
|
settingCacheUpdate() |
|
} |
|
return utils.MergeErrors(errs...) |
|
} |
|
|
|
func SaveSettingItem(item *model.SettingItem) (err error) { |
|
|
|
if _, err := HandleSettingItemHook(item); err != nil { |
|
return err |
|
} |
|
|
|
if err = db.SaveSettingItem(item); err != nil { |
|
return err |
|
} |
|
settingCacheUpdate() |
|
return nil |
|
} |
|
|
|
func DeleteSettingItemByKey(key string) error { |
|
old, err := GetSettingItemByKey(key) |
|
if err != nil { |
|
return errors.WithMessage(err, "failed to get settingItem") |
|
} |
|
if !old.IsDeprecated() { |
|
return errors.Errorf("setting [%s] is not deprecated", key) |
|
} |
|
settingCacheUpdate() |
|
return db.DeleteSettingItemByKey(key) |
|
} |
|
|