mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Add cache for branch divergence on branch list page (#29577)
The branch page for blender project will take 6s because calculating divergence is very slow. This PR will add a cache for the branch divergence calculation. So when the second visit the branch list, it will take only less 200ms.
This commit is contained in:
		| @@ -16,9 +16,11 @@ import ( | |||||||
| 	issues_model "code.gitea.io/gitea/models/issues" | 	issues_model "code.gitea.io/gitea/models/issues" | ||||||
| 	repo_model "code.gitea.io/gitea/models/repo" | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
|  | 	"code.gitea.io/gitea/modules/cache" | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
| 	"code.gitea.io/gitea/modules/gitrepo" | 	"code.gitea.io/gitea/modules/gitrepo" | ||||||
| 	"code.gitea.io/gitea/modules/graceful" | 	"code.gitea.io/gitea/modules/graceful" | ||||||
|  | 	"code.gitea.io/gitea/modules/json" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/optional" | 	"code.gitea.io/gitea/modules/optional" | ||||||
| 	"code.gitea.io/gitea/modules/queue" | 	"code.gitea.io/gitea/modules/queue" | ||||||
| @@ -99,7 +101,6 @@ func LoadBranches(ctx context.Context, repo *repo_model.Repository, gitRepo *git | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, nil, 0, fmt.Errorf("loadOneBranch: %v", err) | 			return nil, nil, 0, fmt.Errorf("loadOneBranch: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		branches = append(branches, branch) | 		branches = append(branches, branch) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -109,10 +110,44 @@ func LoadBranches(ctx context.Context, repo *repo_model.Repository, gitRepo *git | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, nil, 0, fmt.Errorf("loadOneBranch: %v", err) | 		return nil, nil, 0, fmt.Errorf("loadOneBranch: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return defaultBranch, branches, totalNumOfBranches, nil | 	return defaultBranch, branches, totalNumOfBranches, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func getDivergenceCacheKey(repoID int64, branchName string) string { | ||||||
|  | 	return fmt.Sprintf("%d-%s", repoID, branchName) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // getDivergenceFromCache gets the divergence from cache | ||||||
|  | func getDivergenceFromCache(repoID int64, branchName string) (*git.DivergeObject, bool) { | ||||||
|  | 	data := cache.GetCache().Get(getDivergenceCacheKey(repoID, branchName)) | ||||||
|  | 	res := git.DivergeObject{ | ||||||
|  | 		Ahead:  -1, | ||||||
|  | 		Behind: -1, | ||||||
|  | 	} | ||||||
|  | 	s, ok := data.([]byte) | ||||||
|  | 	if !ok || len(s) == 0 { | ||||||
|  | 		return &res, false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := json.Unmarshal(s, &res); err != nil { | ||||||
|  | 		log.Error("json.UnMarshal failed: %v", err) | ||||||
|  | 		return &res, false | ||||||
|  | 	} | ||||||
|  | 	return &res, true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func putDivergenceFromCache(repoID int64, branchName string, divergence *git.DivergeObject) error { | ||||||
|  | 	bs, err := json.Marshal(divergence) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return cache.GetCache().Put(getDivergenceCacheKey(repoID, branchName), bs, 30*24*60*60) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func DelDivergenceFromCache(repoID int64, branchName string) error { | ||||||
|  | 	return cache.GetCache().Delete(getDivergenceCacheKey(repoID, branchName)) | ||||||
|  | } | ||||||
|  |  | ||||||
| func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *git_model.Branch, protectedBranches *git_model.ProtectedBranchRules, | func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *git_model.Branch, protectedBranches *git_model.ProtectedBranchRules, | ||||||
| 	repoIDToRepo map[int64]*repo_model.Repository, | 	repoIDToRepo map[int64]*repo_model.Repository, | ||||||
| 	repoIDToGitRepo map[int64]*git.Repository, | 	repoIDToGitRepo map[int64]*git.Repository, | ||||||
| @@ -130,10 +165,18 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g | |||||||
|  |  | ||||||
| 	// it's not default branch | 	// it's not default branch | ||||||
| 	if repo.DefaultBranch != dbBranch.Name && !dbBranch.IsDeleted { | 	if repo.DefaultBranch != dbBranch.Name && !dbBranch.IsDeleted { | ||||||
| 		var err error | 		var cached bool | ||||||
| 		divergence, err = files_service.CountDivergingCommits(ctx, repo, git.BranchPrefix+branchName) | 		divergence, cached = getDivergenceFromCache(repo.ID, dbBranch.Name) | ||||||
| 		if err != nil { | 		if !cached { | ||||||
| 			log.Error("CountDivergingCommits: %v", err) | 			var err error | ||||||
|  | 			divergence, err = files_service.CountDivergingCommits(ctx, repo, git.BranchPrefix+branchName) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error("CountDivergingCommits: %v", err) | ||||||
|  | 			} else { | ||||||
|  | 				if err = putDivergenceFromCache(repo.ID, dbBranch.Name, divergence); err != nil { | ||||||
|  | 					log.Error("putDivergenceFromCache: %v", err) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -220,6 +220,11 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				// delete cache for divergence | ||||||
|  | 				if err := DelDivergenceFromCache(repo.ID, branch); err != nil { | ||||||
|  | 					log.Error("DelDivergenceFromCache: %v", err) | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				commits := repo_module.GitToPushCommits(l) | 				commits := repo_module.GitToPushCommits(l) | ||||||
| 				commits.HeadCommit = repo_module.CommitToPushCommit(newCommit) | 				commits.HeadCommit = repo_module.CommitToPushCommit(newCommit) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user