summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/cache/cache.go26
-rw-r--r--modules/cache/last_commit.go64
-rw-r--r--modules/git/cache.go6
-rw-r--r--modules/git/commit_info.go45
-rw-r--r--modules/setting/cache.go54
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")
+ }
}