mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-11-25 03:15:19 +08:00
* feat(cache): improve cache management * feat(disk-usage): add cache * feat(disk-usage): add refresh * fix(disk-usage): cache with ttl * feat(cache): implement KeyedCache and TypedCache for improved caching mechanism * fix(copy): update object retrieval to use Get instead of GetUnwrap * refactor(cache): simplify DirectoryCache structure and improve object management * fix(cache): correct cache entry initialization and key deletion logic in TypedCache * refactor(driver): remove GetObjInfo interface and simplify Link function logic https://github.com/OpenListTeam/OpenList/pull/888/files#r2430925783 * fix(link): optimize link retrieval and caching logic * refactor(cache): consolidate cache management and improve directory cache handling * fix(cache): add cache control based on storage configuration in List function * . * refactor: replace fmt.Sprintf with strconv for integer conversions * refactor(cache): enhance cache entry management with Expirable interface * fix(cache): improve link reference acquisition logic to handle expiration * refactor: replace OnlyLinkMFile with NoLinkSF in driver configurations and logic * refactor(link): enhance link caching logic with dynamic type keys based on IP and User-Agent * feat(drivers): add LinkCacheType to driver configurations for enhanced caching * refactor(cache): streamline directory object management in cache operations * refactor(cache): remove unnecessary 'dirty' field from CacheEntry structure * refactor(cache): replace 'dirty' field with bitwise flags * refactor(io): 调高SyncClosers.AcquireReference的优先级 * refactor(link): 优化链接获取逻辑,增加重 * refactor(link): 添加RequireReference字段以增强链接管理 * refactor(link): 移除MFile字段,改用RangeReader * refactor: 移除不必要的NoLinkSF字段 * refactor(cache): 修改目录缓存的脏标志定义和更新逻辑 * feat(cache): add expiration gc --------- Co-authored-by: KirCute <951206789@qq.com> Co-authored-by: KirCute <kircute@foxmail.com> Co-authored-by: j2rong4cn <j2rong@qq.com>
206 lines
5.1 KiB
Go
206 lines
5.1 KiB
Go
package op
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/OpenListTeam/OpenList/v4/internal/db"
|
|
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
|
"github.com/OpenListTeam/OpenList/v4/pkg/singleflight"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var settingG singleflight.Group[*model.SettingItem]
|
|
var settingCacheF = func(item *model.SettingItem) {
|
|
Cache.SetSetting(item.Key, item)
|
|
}
|
|
|
|
var settingGroupG singleflight.Group[[]model.SettingItem]
|
|
var settingGroupCacheF = func(key string, items []model.SettingItem) {
|
|
Cache.SetSettingGroup(key, items)
|
|
}
|
|
|
|
var settingChangingCallbacks = make([]func(), 0)
|
|
|
|
func RegisterSettingChangingCallback(f func()) {
|
|
settingChangingCallbacks = append(settingChangingCallbacks, f)
|
|
}
|
|
|
|
func SettingCacheUpdate() {
|
|
Cache.ClearAll()
|
|
for _, cb := range settingChangingCallbacks {
|
|
cb()
|
|
}
|
|
}
|
|
|
|
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, exists := Cache.GetSettingGroup("ALL_SETTING_ITEMS"); exists {
|
|
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, exists := Cache.GetSettingGroup("ALL_PUBLIC_SETTING_ITEMS"); exists {
|
|
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, exists := Cache.GetSetting(key); exists {
|
|
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 := fmt.Sprintf("GROUP_%d", group)
|
|
if items, exists := Cache.GetSettingGroup(key); exists {
|
|
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)
|
|
|
|
keyParts := make([]string, 0, len(groups))
|
|
for _, g := range groups {
|
|
keyParts = append(keyParts, strconv.Itoa(g))
|
|
}
|
|
key := "GROUPS_" + strings.Join(keyParts, "_")
|
|
|
|
if items, exists := Cache.GetSettingGroup(key); exists {
|
|
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 {
|
|
for i := range items {
|
|
item := &items[i]
|
|
if it, ok := MigrationSettingItems[item.Key]; ok &&
|
|
item.Value == it.MigrationValue {
|
|
item.Value = it.Value
|
|
}
|
|
if ok, err := HandleSettingItemHook(item); ok && err != nil {
|
|
return fmt.Errorf("failed to execute hook on %s: %+v", item.Key, err)
|
|
}
|
|
}
|
|
err := db.SaveSettingItems(items)
|
|
if err != nil {
|
|
return fmt.Errorf("failed save setting: %+v", err)
|
|
}
|
|
SettingCacheUpdate()
|
|
return nil
|
|
}
|
|
|
|
func SaveSettingItem(item *model.SettingItem) (err error) {
|
|
if it, ok := MigrationSettingItems[item.Key]; ok &&
|
|
item.Value == it.MigrationValue {
|
|
item.Value = it.Value
|
|
}
|
|
// hook
|
|
if _, err := HandleSettingItemHook(item); err != nil {
|
|
return fmt.Errorf("failed to execute hook on %s: %+v", item.Key, err)
|
|
}
|
|
// update
|
|
if err = db.SaveSettingItem(item); err != nil {
|
|
return fmt.Errorf("failed save setting on %s: %+v", item.Key, 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)
|
|
}
|
|
|
|
type MigrationValueItem struct {
|
|
MigrationValue, Value string
|
|
}
|
|
|
|
var MigrationSettingItems map[string]MigrationValueItem
|