refactor: split the db package hook and cache to the op package (#2747)
* refactor:separate the setting method from the db package to the op package and add the cache * refactor:separate the meta method from the db package to the op package * fix:setting not load database data * refactor:separate the user method from the db package to the op package * refactor:remove user JoinPath error * fix:op package user cache * refactor:fs package list method * fix:tile virtual paths (close #2743) * Revert "refactor:remove user JoinPath error" This reverts commit 4e20daaf9e700da047000d4fd4900abbe05c3848. * clean path directly may lead to unknown behavior * fix: The path of the meta passed in must be prefix of reqPath * chore: rename all virtualPath to mountPath * fix: `getStoragesByPath` and `GetStorageVirtualFilesByPath` is_sub_path: /a/b isn't subpath of /a/bc * fix: don't save setting if hook error Co-authored-by: Noah Hsu <i@nn.ci>
This commit is contained in:
198
internal/op/setting.go
Normal file
198
internal/op/setting.go
Normal file
@ -0,0 +1,198 @@
|
||||
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) {
|
||||
// hook
|
||||
if _, err := HandleSettingItemHook(item); err != nil {
|
||||
return err
|
||||
}
|
||||
// update
|
||||
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)
|
||||
}
|
Reference in New Issue
Block a user