diff --git a/go.mod b/go.mod index df1207a25..1fa4b62f8 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/avast/retry-go v3.0.0+incompatible github.com/aws/aws-sdk-go v1.55.7 github.com/blevesearch/bleve/v2 v2.5.2 + github.com/bmatcuk/doublestar/v4 v4.9.1 github.com/caarlos0/env/v9 v9.0.0 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.6 diff --git a/go.sum b/go.sum index 377e31868..6b590a8be 100644 --- a/go.sum +++ b/go.sum @@ -180,6 +180,8 @@ github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFx github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw= github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww= github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs= +github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE= +github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= github.com/bodgit/sevenzip v1.6.1 h1:kikg2pUMYC9ljU7W9SaqHXhym5HyKm8/M/jd31fYan4= diff --git a/internal/model/storage.go b/internal/model/storage.go index 863464cb3..da4ce24f6 100644 --- a/internal/model/storage.go +++ b/internal/model/storage.go @@ -5,18 +5,19 @@ import ( ) type Storage struct { - ID uint `json:"id" gorm:"primaryKey"` // unique key - MountPath string `json:"mount_path" gorm:"unique" binding:"required"` // must be standardized - Order int `json:"order"` // use to sort - Driver string `json:"driver"` // driver used - CacheExpiration int `json:"cache_expiration"` // cache expire time - Status string `json:"status"` - Addition string `json:"addition" gorm:"type:text"` // Additional information, defined in the corresponding driver - Remark string `json:"remark"` - Modified time.Time `json:"modified"` - Disabled bool `json:"disabled"` // if disabled - DisableIndex bool `json:"disable_index"` - EnableSign bool `json:"enable_sign"` + ID uint `json:"id" gorm:"primaryKey"` // unique key + MountPath string `json:"mount_path" gorm:"unique" binding:"required"` // must be standardized + Order int `json:"order"` // use to sort + Driver string `json:"driver"` // driver used + CacheExpiration int `json:"cache_expiration"` // cache expire time + CustomCachePolicies string `json:"custom_cache_policies" gorm:"type:text"` + Status string `json:"status"` + Addition string `json:"addition" gorm:"type:text"` // Additional information, defined in the corresponding driver + Remark string `json:"remark"` + Modified time.Time `json:"modified"` + Disabled bool `json:"disabled"` // if disabled + DisableIndex bool `json:"disable_index"` + EnableSign bool `json:"enable_sign"` Sort Proxy } diff --git a/internal/op/driver.go b/internal/op/driver.go index f25b3a6b1..6c4e7d265 100644 --- a/internal/op/driver.go +++ b/internal/op/driver.go @@ -80,6 +80,13 @@ func getMainItems(config driver.Config) []driver.Item { Required: true, Help: "The cache expiration time for this storage", }) + items = append(items, driver.Item{ + Name: "custom_cache_policies", + Type: conf.TypeText, + Default: "", + Required: false, + Help: "The cache expiration rules for this storage", + }) } if config.MustProxy() { items = append(items, driver.Item{ diff --git a/internal/op/fs.go b/internal/op/fs.go index 087857f5d..dc7d01742 100644 --- a/internal/op/fs.go +++ b/internal/op/fs.go @@ -4,6 +4,7 @@ import ( "context" stdpath "path" "strconv" + "strings" "time" "github.com/OpenListTeam/OpenList/v4/internal/conf" @@ -13,6 +14,7 @@ import ( "github.com/OpenListTeam/OpenList/v4/internal/stream" "github.com/OpenListTeam/OpenList/v4/pkg/singleflight" "github.com/OpenListTeam/OpenList/v4/pkg/utils" + "github.com/bmatcuk/doublestar/v4" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "golang.org/x/time/rate" @@ -71,8 +73,34 @@ func List(ctx context.Context, storage driver.Driver, path string, args model.Li if !storage.Config().NoCache { if len(files) > 0 { log.Debugf("set cache: %s => %+v", key, files) - ttl := time.Minute * time.Duration(storage.GetStorage().CacheExpiration) - Cache.dirCache.SetWithTTL(key, newDirectoryCache(files), ttl) + + ttl := storage.GetStorage().CacheExpiration + + customCachePolicies := storage.GetStorage().CustomCachePolicies + if len(customCachePolicies) > 0 { + configPolicies := strings.Split(customCachePolicies, "\n") + for _, configPolicy := range configPolicies { + policy := strings.Split(strings.TrimSpace(configPolicy), ":") + if len(policy) != 2 { + log.Warnf("Malformed custom cache policy entry: %s in storage %s for path %s. Expected format: pattern:ttl", configPolicy, storage.GetStorage().MountPath, path) + continue + } + if match, err1 := doublestar.Match(policy[0], path); err1 != nil { + log.Warnf("Invalid glob pattern in custom cache policy: %s, error: %v", policy[0], err1) + continue + } else if !match { + continue + } + + if configTtl, err1 := strconv.ParseInt(policy[1], 10, 64); err1 == nil { + ttl = int(configTtl) + break + } + } + } + + duration := time.Minute * time.Duration(ttl) + Cache.dirCache.SetWithTTL(key, newDirectoryCache(files), duration) } else { log.Debugf("del cache: %s", key) Cache.deleteDirectoryTree(key)