| 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) |
| } |
|
|