You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

last_commit_cache.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package git
  4. import (
  5. "fmt"
  6. "code.gitea.io/gitea/modules/log"
  7. "code.gitea.io/gitea/modules/setting"
  8. "github.com/minio/sha256-simd"
  9. )
  10. // Cache represents a caching interface
  11. type Cache interface {
  12. // Put puts value into cache with key and expire time.
  13. Put(key string, val any, timeout int64) error
  14. // Get gets cached value by given key.
  15. Get(key string) any
  16. }
  17. func getCacheKey(repoPath, commitID, entryPath string) string {
  18. hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, commitID, entryPath)))
  19. return fmt.Sprintf("last_commit:%x", hashBytes)
  20. }
  21. // LastCommitCache represents a cache to store last commit
  22. type LastCommitCache struct {
  23. repoPath string
  24. ttl func() int64
  25. repo *Repository
  26. commitCache map[string]*Commit
  27. cache Cache
  28. }
  29. // NewLastCommitCache creates a new last commit cache for repo
  30. func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache Cache) *LastCommitCache {
  31. if cache == nil {
  32. return nil
  33. }
  34. if count < setting.CacheService.LastCommit.CommitsCount {
  35. return nil
  36. }
  37. return &LastCommitCache{
  38. repoPath: repoPath,
  39. repo: gitRepo,
  40. ttl: setting.LastCommitCacheTTLSeconds,
  41. cache: cache,
  42. }
  43. }
  44. // Put put the last commit id with commit and entry path
  45. func (c *LastCommitCache) Put(ref, entryPath, commitID string) error {
  46. if c == nil || c.cache == nil {
  47. return nil
  48. }
  49. log.Debug("LastCommitCache save: [%s:%s:%s]", ref, entryPath, commitID)
  50. return c.cache.Put(getCacheKey(c.repoPath, ref, entryPath), commitID, c.ttl())
  51. }
  52. // Get gets the last commit information by commit id and entry path
  53. func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) {
  54. if c == nil || c.cache == nil {
  55. return nil, nil
  56. }
  57. commitID, ok := c.cache.Get(getCacheKey(c.repoPath, ref, entryPath)).(string)
  58. if !ok || commitID == "" {
  59. return nil, nil
  60. }
  61. log.Debug("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, commitID)
  62. if c.commitCache != nil {
  63. if commit, ok := c.commitCache[commitID]; ok {
  64. log.Debug("LastCommitCache hit level 2: [%s:%s:%s]", ref, entryPath, commitID)
  65. return commit, nil
  66. }
  67. }
  68. commit, err := c.repo.GetCommit(commitID)
  69. if err != nil {
  70. return nil, err
  71. }
  72. if c.commitCache == nil {
  73. c.commitCache = make(map[string]*Commit)
  74. }
  75. c.commitCache[commitID] = commit
  76. return commit, nil
  77. }
  78. // GetCommitByPath gets the last commit for the entry in the provided commit
  79. func (c *LastCommitCache) GetCommitByPath(commitID, entryPath string) (*Commit, error) {
  80. sha, err := NewIDFromString(commitID)
  81. if err != nil {
  82. return nil, err
  83. }
  84. lastCommit, err := c.Get(sha.String(), entryPath)
  85. if err != nil || lastCommit != nil {
  86. return lastCommit, err
  87. }
  88. lastCommit, err = c.repo.getCommitByPathWithID(sha, entryPath)
  89. if err != nil {
  90. return nil, err
  91. }
  92. if err := c.Put(commitID, entryPath, lastCommit.ID.String()); err != nil {
  93. log.Error("Unable to cache %s as the last commit for %q in %s %s. Error %v", lastCommit.ID.String(), entryPath, commitID, c.repoPath, err)
  94. }
  95. return lastCommit, nil
  96. }