diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/cache/cache.go | 26 | ||||
-rw-r--r-- | modules/cache/last_commit.go | 64 | ||||
-rw-r--r-- | modules/git/cache.go | 6 | ||||
-rw-r--r-- | modules/git/commit_info.go | 45 | ||||
-rw-r--r-- | modules/setting/cache.go | 54 |
5 files changed, 176 insertions, 19 deletions
diff --git a/modules/cache/cache.go b/modules/cache/cache.go index 20d23f3b5b..e3a905e3fa 100644 --- a/modules/cache/cache.go +++ b/modules/cache/cache.go @@ -16,20 +16,28 @@ import ( _ "gitea.com/macaron/cache/redis" ) -var conn mc.Cache +var ( + conn mc.Cache +) + +func newCache(cacheConfig setting.Cache) (mc.Cache, error) { + return mc.NewCacher(cacheConfig.Adapter, mc.Options{ + Adapter: cacheConfig.Adapter, + AdapterConfig: cacheConfig.Conn, + Interval: cacheConfig.Interval, + }) +} // NewContext start cache service func NewContext() error { - if setting.CacheService == nil || conn != nil { - return nil + var err error + + if conn == nil && setting.CacheService.Enabled { + if conn, err = newCache(setting.CacheService.Cache); err != nil { + return err + } } - var err error - conn, err = mc.NewCacher(setting.CacheService.Adapter, mc.Options{ - Adapter: setting.CacheService.Adapter, - AdapterConfig: setting.CacheService.Conn, - Interval: setting.CacheService.Interval, - }) return err } diff --git a/modules/cache/last_commit.go b/modules/cache/last_commit.go new file mode 100644 index 0000000000..2fd9313bd1 --- /dev/null +++ b/modules/cache/last_commit.go @@ -0,0 +1,64 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + + mc "gitea.com/macaron/cache" + "gopkg.in/src-d/go-git.v4/plumbing/object" +) + +// LastCommitCache represents a cache to store last commit +type LastCommitCache struct { + repoPath string + ttl int64 + repo *git.Repository + commitCache map[string]*object.Commit + mc.Cache +} + +// NewLastCommitCache creates a new last commit cache for repo +func NewLastCommitCache(repoPath string, gitRepo *git.Repository, ttl int64) *LastCommitCache { + return &LastCommitCache{ + repoPath: repoPath, + repo: gitRepo, + commitCache: make(map[string]*object.Commit), + ttl: ttl, + Cache: conn, + } +} + +// Get get the last commit information by commit id and entry path +func (c LastCommitCache) Get(ref, entryPath string) (*object.Commit, error) { + v := c.Cache.Get(fmt.Sprintf("last_commit:%s:%s:%s", c.repoPath, ref, entryPath)) + if vs, ok := v.(string); ok { + log.Trace("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs) + if commit, ok := c.commitCache[vs]; ok { + log.Trace("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, vs) + return commit, nil + } + id, err := c.repo.ConvertToSHA1(vs) + if err != nil { + return nil, err + } + commit, err := c.repo.GoGitRepo().CommitObject(id) + if err != nil { + return nil, err + } + c.commitCache[vs] = commit + return commit, nil + } + return nil, nil +} + +// Put put the last commit id with commit and entry path +func (c LastCommitCache) Put(ref, entryPath, commitID string) error { + log.Trace("LastCommitCache save: [%s:%s:%s]", ref, entryPath, commitID) + return c.Cache.Put(fmt.Sprintf("last_commit:%s:%s:%s", c.repoPath, ref, entryPath), commitID, c.ttl) +} diff --git a/modules/git/cache.go b/modules/git/cache.go index dbbbafae4c..39daf5c49d 100644 --- a/modules/git/cache.go +++ b/modules/git/cache.go @@ -4,8 +4,10 @@ package git +import "gopkg.in/src-d/go-git.v4/plumbing/object" + // LastCommitCache cache type LastCommitCache interface { - Get(repoPath, ref, entryPath string) (*Commit, error) - Put(repoPath, ref, entryPath string, commit *Commit) error + Get(ref, entryPath string) (*object.Commit, error) + Put(ref, entryPath, commitID string) error } diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go index e74ddbfb05..69fd7f3563 100644 --- a/modules/git/commit_info.go +++ b/modules/git/commit_info.go @@ -5,6 +5,8 @@ package git import ( + "path" + "github.com/emirpasic/gods/trees/binaryheap" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/object" @@ -30,7 +32,29 @@ func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCom return nil, nil, err } - revs, err := getLastCommitForPaths(c, treePath, entryPaths) + var revs map[string]*object.Commit + if cache != nil { + var unHitPaths []string + revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, cache) + if err != nil { + return nil, nil, err + } + if len(unHitPaths) > 0 { + revs2, err := getLastCommitForPaths(c, treePath, unHitPaths) + if err != nil { + return nil, nil, err + } + + for k, v := range revs2 { + if err := cache.Put(commit.ID.String(), path.Join(treePath, k), v.ID().String()); err != nil { + return nil, nil, err + } + revs[k] = v + } + } + } else { + revs, err = getLastCommitForPaths(c, treePath, entryPaths) + } if err != nil { return nil, nil, err } @@ -127,6 +151,25 @@ func getFileHashes(c cgobject.CommitNode, treePath string, paths []string) (map[ return hashes, nil } +func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache LastCommitCache) (map[string]*object.Commit, []string, error) { + var unHitEntryPaths []string + var results = make(map[string]*object.Commit) + for _, p := range paths { + lastCommit, err := cache.Get(commitID, path.Join(treePath, p)) + if err != nil { + return nil, nil, err + } + if lastCommit != nil { + results[p] = lastCommit + continue + } + + unHitEntryPaths = append(unHitEntryPaths, p) + } + + return results, unHitEntryPaths, nil +} + func getLastCommitForPaths(c cgobject.CommitNode, treePath string, paths []string) (map[string]*object.Commit, error) { // We do a tree traversal with nodes sorted by commit time heap := binaryheap.NewWith(func(a, b interface{}) int { diff --git a/modules/setting/cache.go b/modules/setting/cache.go index babb62baea..34a212db18 100644 --- a/modules/setting/cache.go +++ b/modules/setting/cache.go @@ -13,31 +13,71 @@ import ( // Cache represents cache settings type Cache struct { + Enabled bool Adapter string Interval int Conn string - TTL time.Duration + TTL time.Duration `ini:"ITEM_TTL"` } var ( // CacheService the global cache - CacheService *Cache + CacheService = struct { + Cache + + LastCommit struct { + Enabled bool + TTL time.Duration `ini:"ITEM_TTL"` + CommitsCount int64 + } `ini:"cache.last_commit"` + }{ + Cache: Cache{ + Enabled: true, + Adapter: "memory", + Interval: 60, + TTL: 16 * time.Hour, + }, + LastCommit: struct { + Enabled bool + TTL time.Duration `ini:"ITEM_TTL"` + CommitsCount int64 + }{ + Enabled: true, + TTL: 8760 * time.Hour, + CommitsCount: 1000, + }, + } ) func newCacheService() { sec := Cfg.Section("cache") - CacheService = &Cache{ - Adapter: sec.Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}), + if err := sec.MapTo(&CacheService); err != nil { + log.Fatal("Failed to map Cache settings: %v", err) } + + CacheService.Adapter = sec.Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}) switch CacheService.Adapter { case "memory": - CacheService.Interval = sec.Key("INTERVAL").MustInt(60) case "redis", "memcache": CacheService.Conn = strings.Trim(sec.Key("HOST").String(), "\" ") + case "": // disable cache + CacheService.Enabled = false default: log.Fatal("Unknown cache adapter: %s", CacheService.Adapter) } - CacheService.TTL = sec.Key("ITEM_TTL").MustDuration(16 * time.Hour) - log.Info("Cache Service Enabled") + if CacheService.Enabled { + log.Info("Cache Service Enabled") + } + + sec = Cfg.Section("cache.last_commit") + if !CacheService.Enabled { + CacheService.LastCommit.Enabled = false + } + + CacheService.LastCommit.CommitsCount = sec.Key("COMMITS_COUNT").MustInt64(1000) + + if CacheService.LastCommit.Enabled { + log.Info("Last Commit Cache Service Enabled") + } } |