pages-server/pages/cache_owner.go
2024-09-14 11:53:32 +08:00

111 lines
2.6 KiB
Go

package pages
import (
"code.gitea.io/sdk/gitea"
"github.com/patrickmn/go-cache"
"github.com/pkg/errors"
"net/http"
"strings"
"sync"
"time"
)
type OwnerCache struct {
ttl time.Duration
*cache.Cache
mutexes sync.Map
}
func NewOwnerCache(ttl time.Duration, cacheTtl time.Duration) OwnerCache {
return OwnerCache{
ttl: ttl,
mutexes: sync.Map{},
Cache: cache.New(cacheTtl, cacheTtl*2),
}
}
type OwnerConfig struct {
FetchTime int64 `json:"fetch_time,omitempty"`
Repos map[string]bool `json:"repos,omitempty"`
LowerRepos map[string]bool `json:"lower_repos,omitempty"`
}
func NewOwnerConfig() *OwnerConfig {
return &OwnerConfig{
Repos: make(map[string]bool),
LowerRepos: make(map[string]bool),
}
}
// 直接查询 Owner 信息
func getOwner(giteaConfig *GiteaConfig, owner string) (*OwnerConfig, error) {
result := NewOwnerConfig()
repos, resp, err := giteaConfig.Client.ListOrgRepos(owner, gitea.ListOrgReposOptions{
ListOptions: gitea.ListOptions{
PageSize: 999,
},
})
if err != nil && resp.StatusCode == http.StatusNotFound {
// 调用用户接口查询
repos, resp, err = giteaConfig.Client.ListUserRepos(owner, gitea.ListReposOptions{
ListOptions: gitea.ListOptions{
PageSize: 999,
},
})
if err != nil && resp.StatusCode == http.StatusNotFound {
return nil, errors.Wrap(ErrorNotFound, err.Error())
} else if err != nil {
return nil, err
}
} else if err != nil {
return nil, err
}
for _, repo := range repos {
result.Repos[repo.Name] = true
result.LowerRepos[strings.ToLower(repo.Name)] = true
}
result.FetchTime = time.Now().UnixMilli()
return result, nil
}
func (c *OwnerCache) GetOwnerConfig(giteaConfig *GiteaConfig, owner string) (*OwnerConfig, error) {
raw, _ := c.Get(owner)
// 每固定时间刷新一次
nextTime := time.Now().UnixMilli() - c.ttl.Milliseconds()
var result *OwnerConfig
if raw != nil {
result = raw.(*OwnerConfig)
if nextTime > result.FetchTime {
//移除旧数据
c.Delete(owner)
raw = nil
}
}
if raw == nil {
lock := c.Lock(owner)
defer lock()
if raw, find := c.Get(owner); find {
return raw.(*OwnerConfig), nil
}
//不存在缓存
var err error
result, err = getOwner(giteaConfig, owner)
if err != nil {
return nil, errors.Wrap(err, "owner config not found")
}
c.Set(owner, result, cache.DefaultExpiration)
}
return result, nil
}
func (c *OwnerCache) Lock(any string) func() {
value, _ := c.mutexes.LoadOrStore(any, &sync.Mutex{})
mtx := value.(*sync.Mutex)
mtx.Lock()
return func() { mtx.Unlock() }
}
func (c *OwnerConfig) Exists(repo string) bool {
return c.LowerRepos[strings.ToLower(repo)]
}