2022-06-25 13:36:35 +00:00
|
|
|
package db
|
2022-06-16 13:59:49 +00:00
|
|
|
|
|
|
|
import (
|
2022-08-03 06:26:59 +00:00
|
|
|
stdpath "path"
|
|
|
|
"time"
|
|
|
|
|
2022-06-16 13:59:49 +00:00
|
|
|
"github.com/Xhofe/go-cache"
|
2022-06-23 08:03:27 +00:00
|
|
|
"github.com/alist-org/alist/v3/internal/errs"
|
2022-06-16 13:59:49 +00:00
|
|
|
"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"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
)
|
|
|
|
|
|
|
|
var metaCache = cache.NewMemCache(cache.WithShards[*model.Meta](2))
|
|
|
|
|
|
|
|
// metaG maybe not needed
|
|
|
|
var metaG singleflight.Group[*model.Meta]
|
|
|
|
|
|
|
|
func GetNearestMeta(path string) (*model.Meta, error) {
|
2022-06-23 09:04:37 +00:00
|
|
|
path = utils.StandardizePath(path)
|
2022-06-16 13:59:49 +00:00
|
|
|
meta, err := GetMetaByPath(path)
|
|
|
|
if err == nil {
|
|
|
|
return meta, nil
|
|
|
|
}
|
|
|
|
if errors.Cause(err) != gorm.ErrRecordNotFound {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if path == "/" {
|
2022-06-23 08:03:27 +00:00
|
|
|
return nil, errors.WithStack(errs.MetaNotFound)
|
2022-06-16 13:59:49 +00:00
|
|
|
}
|
|
|
|
return GetNearestMeta(stdpath.Dir(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMetaByPath(path string) (*model.Meta, error) {
|
|
|
|
meta, ok := metaCache.Get(path)
|
|
|
|
if ok {
|
|
|
|
return meta, nil
|
|
|
|
}
|
|
|
|
meta, err, _ := metaG.Do(path, func() (*model.Meta, error) {
|
|
|
|
meta := model.Meta{Path: path}
|
|
|
|
if err := db.Where(meta).First(&meta).Error; err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed select meta")
|
|
|
|
}
|
2022-06-26 08:55:37 +00:00
|
|
|
metaCache.Set(path, &meta, cache.WithEx[*model.Meta](time.Hour))
|
2022-06-16 13:59:49 +00:00
|
|
|
return &meta, nil
|
|
|
|
})
|
|
|
|
return meta, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMetaById(id uint) (*model.Meta, error) {
|
|
|
|
var u model.Meta
|
|
|
|
if err := db.First(&u, id).Error; err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed get old meta")
|
|
|
|
}
|
|
|
|
return &u, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func CreateMeta(u *model.Meta) error {
|
|
|
|
return errors.WithStack(db.Create(u).Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func UpdateMeta(u *model.Meta) error {
|
|
|
|
old, err := GetMetaById(u.ID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
metaCache.Del(old.Path)
|
|
|
|
return errors.WithStack(db.Save(u).Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMetas(pageIndex, pageSize int) ([]model.Meta, int64, error) {
|
|
|
|
metaDB := db.Model(&model.Meta{})
|
|
|
|
var count int64
|
|
|
|
if err := metaDB.Count(&count).Error; err != nil {
|
|
|
|
return nil, 0, errors.Wrapf(err, "failed get metas count")
|
|
|
|
}
|
|
|
|
var metas []model.Meta
|
|
|
|
if err := metaDB.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&metas).Error; err != nil {
|
|
|
|
return nil, 0, errors.Wrapf(err, "failed get find metas")
|
|
|
|
}
|
|
|
|
return metas, count, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func DeleteMetaById(id uint) error {
|
|
|
|
old, err := GetMetaById(id)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
metaCache.Del(old.Path)
|
|
|
|
return errors.WithStack(db.Delete(&model.Meta{}, id).Error)
|
|
|
|
}
|